Android8.0的Activity的啓動流程(2)

前言

上一篇文章講了應用進程請求AMS啓動Activity過程和Activity在AMS中的啓動過程,而後Activity啓動的代碼邏輯就從AMS所在進程,又從新回到了應用進程所在的ApplicationThread中。咱們還留下了一個問題,Activity的生命週期方法是如何被回調的?,下面咱們就帶着這個疑問,去走一遍源碼,看一下在應用進程中ApplicationThread啓動Activity的過程。java

本文基於android8.0,本文相關源碼文件位置以下:
frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/core/java/android/app/Instrumentation.java
複製代碼

ApplicationThread::scheduleLaunchActivity()

上文結尾講到在ActivityStackSupervisor的realStartActivityLocked()中調用了ApplicationThread中的scheduleLaunchActivity方法,這裏是Activity啓動的開始。ApplicationThread是ActivityThread的內部類,實現了IApplicationThread.stub接口。ActivityThread表明應用程序進程的主線程,它管理着當前應用程序進程的線程。android

咱們來看一下scheduleLaunchActivity的相關源碼:git

//ActivityThread::ApplicationThread
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
     		
    	   ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
 }
複製代碼

上述方法中只是簡單的把從AMS傳過來的有關啓動Activity的參數,封裝成ActivityClientRecord,而後調用sendMessage向H發送LAUNCH_ACTIVITY的消息,而且將ActivityClientRecord做爲參數傳了過去,H是ActivityThread中的內部類,是Handler類型,有關Activity的啓動消息都交給這個Handler處理,爲何這裏要進行切換到主線程處理消息呢?由於此時這裏還運行在Binder的線程池中,不能進行Activity的啓動,因此要切換到主線程中才能進行Activity的生命週期的方法回調。github

下面咱們來看看sendMessage方法。緩存

一、ApplicationThread::sendMessage()

該方法以下:app

//ActivityThread::ApplicationThread
private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
}

 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        //...
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
 }
複製代碼

能夠看到,sendMessage方法中將H.LAUNCH_ACTIVITY與ActivityClientRecord封裝成一個Message,而後調用mH的sendMessage方法,mH就是H的實例,以下:async

final H mH = new H();
複製代碼

熟悉android消息機制的都知道(不瞭解的,能夠看這一篇文章Android消息機制java層),Handler發送消息後,都會統一到handlerMessage方法中處理。ide

咱們來看一下Handler H對消息的處理。函數

二、H::handleMessage()

以下:源碼分析

//ActivityThread.java
private class H extends Handler {
     public static final int LAUNCH_ACTIVITY         = 100;
     public static final int PAUSE_ACTIVITY          = 101;
     public static final int RESUME_ACTIVITY         = 107;
     public static final int DESTROY_ACTIVITY        = 109;
     public static final int BIND_APPLICATION        = 110;
     //...
    public void handleMessage(Message msg) {
        switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                }
                break;
                //...
        }
    }
}
複製代碼

H中有不少關於四大組件的消息處理的字段,如Activity的啓動,這裏咱們只關心前面發送過來的LAUNCH_ACTIVITY字段的消息處理,能夠看到這裏首先把msg中的obj字段轉換爲ActivityClientRecord,而後爲ActivityClientRecord的packageInfo賦值,packageInfo是LoadedApk類型,它表示已加載的APK文件,接下來調用了外部類ActivityThread的handleLaunchActivity方法。

接下來咱們來看一下ActivityThread的handleLaunchActivity方法。

ActivityThread::handleLaunchActivity()

該方法源碼以下:

//ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    //...
    //最終回調Activity的onConfigurationChanged方法
    handleConfigurationChanged(null, null);
    //這裏面獲取WindowManager系統服務的本地代理
    WindowManagerGlobal.initialize();
    //一、關注這裏,啓動Activity,調用了ActivityThread的performLaunchActivity方法,會最終回調Activity的onCreate,onStart方法
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
         //...
        //二、關注這裏,調用了ActivityThread的handleResumeActivity方法,會最終回調Activity的onResume方法
         handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
		//...
    }else {
        //若是出錯了,這裏會告訴AMS中止啓動Activity 
        try {
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}
複製代碼

本文的重點是Activity的生命週期如何被回調,因此上面咱們只須要關注註釋一、2。註釋1中調用了ActivityThread的performLaunchActivity方法,該方法最終完成了Activity對象的建立和啓動過程,若是啓動出錯就會通知AMS中止啓動Activity,而且在註釋2中ActivityThread經過handleResumeActivity將被啓動的Activity置爲Resume狀態。

咱們首先看註釋1的performLaunchActivity方法。

一、ActivityThread::performLaunchActivity()

該方法相關源碼以下:

//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //從ActivityClientRecord中獲取ActivityInfo。
    ActivityInfo aInfo = r.activityInfo;
    //獲取packageInfo,packageInfo是前面講到的LoadedApk類型
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                                       Context.CONTEXT_INCLUDE_CODE);
    }
    //獲取ComponentName
     ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }
     if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
    //建立要啓動Activity的上下文環境
    ContextImpl appContext = createBaseContextForActivity(r);
    //構造Activity對象,並設置參數
    Activity activity = null;
     try {
         	//獲取類加載器
            java.lang.ClassLoader cl = appContext.getClassLoader();
         	//經過Instrumentation,用類加載建立該Activity實例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            //設置相關參數準備初始化Activity
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
          //初始化Activity失敗
          //....
      }
     try {
         //建立Application
         Application app = r.packageInfo.makeApplication(false, mInstrumentation);
         //...
         if (activity != null) {
              //構造Configuration對象
              Configuration config = new Configuration(mCompatConfiguration);
             //...
             //把該Activity和ContextImpl關聯
             appContext.setOuterContext(activity);
             //經過attach方法將上述建立的信息保持到Activity內部,用來完成對Activity的初始化,如ContextImpl,Application,Configuration
             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, r.configCallback);
             //...
             //獲取Activity的主題並設置
             int theme = r.activityInfo.getThemeResource();
             if (theme != 0) {
                    activity.setTheme(theme);
             }
              activity.mCalled = false;
             //一、根據是否須要持久化,調用Instrumentation的callActivityOnCreate方法通知Activity已經被建立,裏面最終會調用Activity的onCreate方法
              if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                  //關注這裏,走這個分支
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
              if (!activity.mCalled) {
                   //...
                  //沒法調用Activity的onCreate方法,拋出異常
                }
              r.activity = activity;
              r.stopped = true;
              if (!r.activity.mFinished) {
                  //二、裏面最終會調用Activity的onStart方法
                  activity.performStart();
                  r.stopped = false;
              }
              if (!r.activity.mFinished) {
                    //根據是否須要持久化,調用Instrumentation的callActivityOnRestoreInstanceState方法通知Activity已經被建立,裏面最終會調用Activity的onRestoreInstanceState方法
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
             //...
         }
          r.paused = true;
         //把ActivityClientRecord緩存起來,以便在之後使用。mActivities的定義:ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
		 mActivities.put(r.token, r);
     } catch (SuperNotCalledException e) {
          //...
     } catch (Exception e) {
          //...
          //拋異常,沒法啓動Activity
      }
    return activity;
}
複製代碼

該方法的主要代碼都貼出來了,並作了註釋,它主要作了如下事情:

  • 一、從ActivityClientRecord中獲取待啓動的Activity的組件信息,如ActivityInfo,ComponentName。

ActivityInfo類用於存儲代碼中AndroidManifes設置的activity節點信息,ComponentName類中保存了該Activity的包名和類名

  • 二、經過createBaseContextForActivity方法建立要啓動Activity的上下文環境ContextImp,並在下面做爲參數傳進attach方法中。

ContextImp是Context的具體實現,Context中的大部分邏輯都是交給ContextImpl來完成,Context中定義了許多與四大組件啓動、系統級服務獲取、類加載、資源獲取等有密切關係的方法,而Activity繼承自ContextThemeWrapper,ContextThemeWrapper繼承自ContextWrapper,ContextWrapper繼承自Context,ContextWrapper內部有一個Context類型的mBase引用,而在Activity的attach方法中會調用attachBaseContext方法把該ContextImp賦值給mBase,因此Activity是ContextImpl的包裝類,Activity擴展了Context中的方法。(這裏就是一個裝飾者模式

  • 三、經過LoadedApk的makeApplication方法建立Application。

makeApplication方法裏面最終是經過Instrumentation的newApplication方法用類加載器建立Application,若是Application已經被建立過了,那麼就不會重複建立,若是建立成功,會緊接着經過Instrumentation的callApplicationOnCreate來調用Application的onCreate方法。

  • 四、經過Instrumentation的newActivity方法用類加載器建立Activity對象。

Instrumentation是一個用來監控應用程序與系統交互的類,經過它能夠建立Activity、Applicationd實例,還與Activity生命週期的回調有關,因此在下文看到mInstrumentation.callActivityOnXX, 通常都是要回調某個Activity的生命週期方法。

  • 五、經過Activity的attach方法來完成一些重要數據的初始化,如ContextImpl,Application,Configuration等。

在attach方法中會建立Window對象(PhoneWindow)並與Activity自身進行關聯,這樣當Window接收到外部的輸入事件後就能夠將事件傳遞給Activity。第2點講過,還會把ContextImpl與Activity關聯。

  • 六、調用Instrumentation的callActivityOnCreate方法,裏面最終會調用Activity的onCreate方法。

這裏就是重點關注的註釋1,註釋還寫到這裏會根據是否須要持久化來調用不一樣參數的mInstrumentation的callActivityOnCreate方法,這個持久化是什麼?其實這是在API 21後,Activity新增的一個」persistableMode「屬性,在AndroidManifest.xml的activity節點將他它設爲android:persistableMode=」persistAcrossReboots,Activity就有了持久化的能力,這時候咱們能夠數據保存在outPersistentState(Bundle類型),那麼即便是關機,仍然能夠恢復這些數據。關於PersistableMode更多信息能夠看這篇文章PersistableMode使Activity數據持久化保存,這不是本文的重點。

因此通常狀況下咱們沒有使用這個屬性,就會走到else分支,調用 mInstrumentation.callActivityOnCreate(activity, r.state)方法。

1.一、Instrumentation::callActivityOnCreate()

該方法源碼以下:

//Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
    	//一、關注這裏,調用了Activity的performCreate方法
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
複製代碼

咱們看註釋1,調用了activity的performCreate方法,見名知意。

1.1.一、Activity::performCreate()

該方法源碼以下:

//Activity.java 
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
    	//一、看到咱們的主角吧!onCreate方法
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }
複製代碼

看註釋1,調用了咱們熟悉的onCreate方法,咱們平時通常在這裏面進行Activity的控件、資源等初始化操做。

下面繼續回到ActivityThread的performLaunchActivity方法,接着上面的第6點。

  • 七、調用Activity的performStart方法,裏面最終會調用Activity的onStart方法。

這裏也就是重點關注的註釋2,下面看一下performStart方法。

1.二、Activity::performStart()

咱們繼續點進去看一下:

//Activity.java
final void performStart() {
    //...
    mCalled = false;
    //一、關注這裏,調用了Instrumentation的callActivityOnStart方法
    mInstrumentation.callActivityOnStart(this);
    if (!mCalled) {
             //...
             //沒法調用Activity的onStart方法,拋出異常
        }
    //...
}
複製代碼

看註釋1,該方法仍是同樣的套路,調用 mInstrumentation.callActivityOnStart方法,咱們看一下 Instrumentation的callActivityOnStart方法:

1.2.一、Instrumentation::callActivityOnStart()

該方法以下:

//Instrumentation.java
public void callActivityOnStart(Activity activity) {
    	//看到咱們的主角吧!onStart方法
        activity.onStart();
    }
複製代碼

很簡單的一句代碼,調用了咱們熟悉的onStart方法。

繼續回到咱們的ActivityThread的performLaunchActivity方法,還有一點沒分析完,接下來到了根據須要調用Instrumentation的callActivityOnRestoreInstanceState方法,裏面最終會調用Activity的onRestoreInstanceState方法,關於這個方法的做用已經不是本文的重點,但咱們能夠得出一個結論,onRestoreInstanceState方法的調用時機是在onStart方法以後。最後ActivityThread把ActivityClientRecord緩存起來。

分析完這個長長的方法,其實跟本文有關也就第六、7點。咱們跳出ActivityThread::performLaunchActivity方法,回到ActivityThread的handleLaunchActivity方法。如今咱們的Activity已經回調了onCreate和onStart方法,接下來應該是onResume方法。

下面咱們咱們接着來看handleLaunchActivity方法中註釋2的handleResumeActivity方法。

二、ActivityThread::handleResumeActivity()

該方法源碼以下:

//ActivityThread.java
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    //從緩存中拿出ActivityClientRecord
    ActivityClientRecord r = mActivities.get(token);
    //...
    //一、主要關注這裏,調用了performResumeActivity方法,這裏最終會調用Activity的onResume方法
    r = performResumeActivity(token, clearHide, reason);
    
    //二、下面if(r != null){}分支裏面的邏輯都是把Activity顯示出來
	if (r != null) {
        //拿到Activity
        final Activity a = r.activity;
        //...
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
         }
        if (r.window == null && !a.mFinished && willBeVisible) {
            //獲得Activity關聯的Window
             r.window = r.activity.getWindow();
            //獲得Activity的DecorView,即Activity的頂級View
            View decor = r.window.getDecorView();
            //先把DecorView設爲不可見
            decor.setVisibility(View.INVISIBLE);
            //獲得ViewManager,用於添加DecorView
            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) {
                 if (!a.mWindowAdded) {
                     a.mWindowAdded = true;
                     //用ViewManager添加DecorView
                     wm.addView(decor, l);
                 }
                 //...
             }
        }
        //...
        //此時用於承載DecorView的Window已經被WM添加了,可是還處於INVISIBLE狀態,因此下面就把它值爲VISIBLE
        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
            //...
             if (r.activity.mVisibleFromClient) {
                 //把Activity顯示出來
                 r.activity.makeVisible();
             }
        }
        
	}else {
        //...
        //Activity不可以Resume,通知AMS結束掉該Activity
    }
}
複製代碼

handleResumeActivity方法裏面的代碼也有點長,這個方法主要是把Activity置爲Resume狀態,並把Activity顯示出來,因此咱們只關注註釋1,註釋2是把Activity值爲VISIBLE狀態,你們要明白的是Activity其實也能夠說是一個View,它的頂級View叫作DecorView,但系統回調完Activity的onResume函數時,只是說明Activity1已經完成全部的資源準備工做,Activity已經作好顯示給用戶的準備,因此還要經過相似於setVisible的方式把它顯示出來,這個過程涉及到WindowManage的相關知識,爲何要這樣作?你們能夠看這篇文章Window,WindowManager和WindowManagerService之間的關係瞭解一下,因此註釋2不是本文重點就不講了。

下面咱們來看註釋1的performResumeActivity方法。

2.1 ActivityThread::performResumeActivity()

該方法主要源碼以下:

//ActivityThread.java
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
    //從緩存中拿到ActivityClientRecord
     ActivityClientRecord r = mActivities.get(token);
    if (r != null && !r.activity.mFinished) {
         if (clearHide) {
                r.hideForNow = false;
                r.activity.mStartedActivity = false;
          }
        //...
        try {
            //...
            //一、主要關注這裏,調用了Activity的performResume方法
            r.activity.performResume();
            //...
             r.paused = false;
             r.stopped = false;
             r.state = null;
             r.persistentState = null;
        }catch(Exception e) {
             //...
            //拋異常,沒法resume Activity
        }
    }
    return r;
}
複製代碼

主要關注註釋1,調用了Activity的performResume,和上面的performCreate,performStart很類似。

下面咱們來看Activity的performResume方法。

2.1.1 Activity::performResume()

該方法主要源碼以下:

//Activity.java
final void performResume() {
    //這裏處理Activity生命週期中的Restart流程
    performRestart();
    //...
	mCalled = false;
    //一、關注這裏,調用Instrumentation的callActivityOnResume方法
    mInstrumentation.callActivityOnResume(this);
    if (!mCalled) {
       //...
        //拋異常,沒法調用Activity的onResume方法
    }
}
複製代碼

在這個方法中咱們看到了 performRestart()方法,這個是根據狀況處理Restart流程,裏面會執行onReStart() -> onStart() ,到這裏就執行onResume(), 因此咱們看到註釋1會Instrumentation的callActivityOnResume方法,這個和上面的callActivityOnCreate()、callActivityOnStart()相似。

本着執着的態度,咱們仍是看一下Instrumentation的callActivityOnResume方法。

2.1.二、Instrumentation::callActivityOnResume()
//Instrumentation.java
public void callActivityOnResume(Activity activity) {
    activity.mResumed = true;
    //又看到了咱們的主角之一,onResume方法
    activity.onResume();
    //...
}
複製代碼

該方法先把Activity的mResumed 賦值爲true,而後回調了咱們熟悉的onResume方法。

咱們跳出ActivityThread的handleResumeActivity方法,回到handleLaunchActivity方法,至此handleLaunchActivity方法分析完,Activity已經顯示到用戶面前。

總結

到目前爲止咱們已經回調了Activity的三個生命週期方法:onCreate -> onStart -> onResume,onRestart也介紹了一下,能夠說開頭那個問題已經解解決了一半,我先來看一下本文的時序圖:

因此如今咱們知道了在應用進程中ApplicationThread啓動Activity的過程。

那麼還有三個方法:onPause -> onStop -> onDestory 何時被回調呢?你們都知道Activity有7個生命週期方法,除去onRestart,其餘3個都是一 一對應的,結合前面那篇文章Activity的啓動流程(1)咱們知道:

  • 一、在AMS中含有ApplicatiThread的本地代理,因此AMS所在進程能夠經過這個代理與ActivityThread的主線程通訊,也就能調用ApplicatiThread的一些方法。

  • 二、在應用進程中也含有系統服務AMS的本地代理對象,因此應用進程能夠經過這個代理與AMS通訊,能夠請求AMS啓動一個Activity。

  • 三、雙方都含有雙方的代理,經過Binder,也就創建起雙方的通訊通道。

每一個應用都有本身專屬Activity任務棧,Activity任務棧的管理是在AMS那邊,在本文的狀況下,一個Activity已經被啓動了,該Activity被加入到棧頂中去,若是此時我按back鍵返回上一個Activity,那麼該Activity就會調用相應的回調onPause -> onStop -> onDestory方法,這個過程在AMS那邊對應一個出棧動做,此時AMS也就像啓動Activity調用scheduleLaunchActivity方法那樣調用ApplicationThread中schedulePauseActivity、scheduleStopActivity、scheduleDestroyActivity方法來結束掉這個Activity,這個調用過程是IPC,因此你們經過本文觸類旁通也就明白了Activity的其餘生命週期是如何被回調的,這個過程離不開與AMS的交互。

至此咱們已經走完startActivity後發生的流程。在這整個過程當中也發現了本身日常不少遺落的知識點,讓我更進一步的認識了Activity。但願你們也有所收穫。

參考資料:

Activity生命週期回調是如何被回調的

《Android源碼分析與實戰》

相關文章
相關標籤/搜索