1. 程式人生 > >Activity類組成分析(一)Instrumentation

Activity類組成分析(一)Instrumentation

[toc] # 前言 要了解清楚StartActivity的過程,Activity物件例項的構造過程是重要組成部分;而要弄清楚Activity例項的構造,熟知其重要成員以及設計邏輯是前提,本系列文章主要分析解構Activity類的重要組成成員,以及各成員在Activity的生命週期中扮演什麼角色。 # 解剖 ## 繼承關係 ``` public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, WindowControllerCallback, AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient ``` 可以看到Activity繼承ContextThemeWrapper並實現了很多介面,其中包含了我們熟知的onCreateView、onKeyEvent等等。至於context家族的關係暫時不在本文的討論中了。 ## 重要成員 ### Instrumentation 這個類寫app一般用不到,但是如果寫過測試程式肯定有印象,它有強大的跟蹤、控制Activity生命週期的能力,一般用在測試框架的基類;之所以這麼強大,其實Activity內部關於call生命相關的方法,都是藉由Instrumentation類完成的,如startActivity: ``` * @see #startActivity */ public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { ... Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ... ``` 如app的生命週期方法呼叫: ``` final void performResume(boolean followedByPause, String reason) { dispatchActivityPreResumed(); ... mCalled = false; // mResumed is set by the instrumentation mInstrumentation.callActivityOnResume(this); ``` 那麼一個app有幾個Instrumention例項?是一個Activity擁有一個還是一個app擁有一個?我們來看下它在Activity中如何被賦值的,一步一步尋找答案。 ``` final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { attachBaseContext(context); ... mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; ``` 原來是在attach中被賦值的,那麼attach方法是誰呼叫的?在ActivityThread裡。 ``` private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window); ... } public Instrumentation getInstrumentation() { return mInstrumentation; } ``` 原來mInstrumentation還是ActivityThread的成員變數,我們都知道ActivityThread是一個app有一個例項,那麼基本確認所有的Activity都是共享同一個mInstrumentation了。但是這兒還不是建立Instrumentation的地方,繼續尋找確定答案。我們找到一個new物件的地方。 ``` private void handleBindApplication(AppBindData data) { ... } else { mInstrumentation = new Instrumentation(); } ... } case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ``` handleBindApplication在ActivityThread的looper訊息迴圈中的。那麼一定有人對ActivityThread的handler傳送了BIND_APPLICATION的訊息,查詢後在BindApplication中印證了 ``` public final void bindApplication(String processName, ApplicationInfo appInfo,