ActivityThread.handleLaunchActivity方法分析

開始

在之前的文章Activity的啟動過程分析中,我們詳細分析了act的啟動流程,只是后面的第5步當時礙于篇幅原因無法細說,所以這里單獨拿出來詳細分析下。
示例代碼如下:

Intent intent = new Intent(this, TargetAct.class);
startActivity(intent);

每個Android開發(fā)都知道當我們寫下這樣的代碼時,系統(tǒng)最終會為我們創(chuàng)建一個TargetAct的實例,并展現(xiàn)在我們面前,整體流程可以參看下之前的那篇文章,這里我們只分析最終走到的ActivityThread.handleLaunchActivity方法。

handleLaunchActivity做了哪些事情

  1. 初始化WindowManagerGlobal
  2. 調用performLaunchActivity方法;
  3. 如果第2步執(zhí)行ok的話,調用handleResumeActivity,否則會調用AMS的finishActivity方法來結束這個act。

performLaunchActivity做了哪些事情

  1. 從ActivityClientRecord中得到接下來要啟動act的ComponentName信息;
  2. 通過Instrumentation.newActivity方法,利用LoadedApk的類加載器嘗試創(chuàng)建act的對象;className字符串就是上面第1步ComponentName里的值;
  3. 通過LoadedApk(r.packageInfo字段).makeApplication方法嘗試創(chuàng)建Application對象,在這個方法里會通過Class.newInstance()方法創(chuàng)建Application的對象,并且它的attach、onCreate方法也是在此時被調用的。另外注意下這個方法一進去就有個判斷,代碼如下:
        if (mApplication != null) {
            return mApplication;
        }

也就是說,只是在第一次當mApplication是null的情況下,才會新創(chuàng)建Application對象,否則這個方法只是返回之前創(chuàng)建好的對象并不會多次創(chuàng)建。也就是說一般情況下Application.onCreate()之類的方法會被調用一次。這里其實有個疑問,各位可以想想Application.onCreate()方法會被調用多次嗎,如果會那么是在何種情況下呢?

  1. 為act創(chuàng)建ContextImpl的對象,調用Activity.attach方法;
    源碼如下:
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) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

可以看到此方法完成Activity內部很多重要字段的初始化,特別是mWindow、mWindowManager等字段;

  1. 調用Activity.setTheme方法,如果act申明時指定了theme的話;
  2. 調用Act.onCreate()方法,然后是onStart()方法,如果之前有保存的狀態(tài)那么還會調用onRestoreInstanceState()方法,最后調用onPostCreate()方法,至此整個launch過程算是結束了。

handleResumeActivity方法做了哪些事情

  1. 如果需要,調用Act.onNewIntent()方法;
  2. 如果需要,調用Act.onActivityResult()方法;
  3. 調用act的onRestart、onStart、onResume方法,可以參看Act.performResume()方法源碼;
  4. 將act的DecorView添加到WindowManagerGlobal中,代碼如下:
 if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
} else if (!willBeVisible) {
        if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
        r.hideForNow = true;
}
  1. 調用Act.makeVisible()方法,這樣act的界面才能顯示在用戶面前,代碼如下:
void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 注意這個調用,正是因為它用戶才能看到act的界面內容
        mDecor.setVisibility(View.VISIBLE); 
    }

至此,act就已經展現(xiàn)在用戶面前,并且處于resume狀態(tài),正等待和用戶交互了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容