【系統之音】Activity啓動流程——史上最全最簡潔易懂版 【系統之音】Android系統啓動篇 【朝花夕拾】Android自定義View篇之(一)View繪製流程

        Activity的啓動流程是一個資深Android工程師必須掌握的內容,也是高職級面試中的高頻面試知識點,無論是從事應用層開發,還是Framework開發,其重要性都無需我多言。而要真正理解它,就不可避免地要深入到源碼了,本文將從Android8.1系統源碼入手,來抽絲剝繭。由於Activity的啓動流程涉及到的細節非常多而且複雜,爲了便於讀理解,本文將摒棄衆多的細節,而着重於關鍵流程的梳理。

       儘管簡化了很多細節,但流程還是不少,爲了便於讀者閱讀和理解,筆者會先給出重要的結論和UML序列圖,讀者正確的閱讀方式也是先知道梗概,再結合UML序列圖來看源碼,同時最好能自己再IDE上打開源碼,順着筆者的思路去閱讀,否者會看得暈頭轉向。

 

1、啓動Activity的若干場景

       Activity的啓動有多種途徑,比較常見的有:

    (1)點擊Launcher中的快捷圖標,這種方式進入的是根Activity;

    (2)從其它應用跳轉到某個應用的activity,這種場景下啓動的可以是根Activity,也可以是其它Activity,如:從某些應用撥打電話、開啓相機、打開瀏覽器等;

    (3)同一個應用種從某個組件中啓動Activity。

      而啓動某個Activity的時候,也可能有兩種情形:

    (1)目標Activity所在應用程序進程不存在,也就是此時該應用還沒有啓動的情形;

    (2)目標Activity所在應用程序進程存在,也就是該應用之前啓動過。

      上面這些場景,Activity的啓動流程肯定是存在一定差異的,但核心流程基本一致,都是在基本流程基礎上或增或減部分流程。從Launcher中點擊快捷圖標啓動一個根Activity的場景,就比較有代表性,本文將以此情形來介紹Activity的啓動流程。

 

2、根Activity啓動流程概貌

       這裏,我先給出結論,讀者們先宏觀看看這其中大概有哪幾步。先上圖:

       從Launcher中點擊快捷圖標到啓動根Activity過程中,主要涉及到4個進程的交互:Launcher所在應用進程、ActivityManagerService(後文簡稱AMS)所在的SystemServe系統進程、Zygote系統進程、目標根Activity所在的應用程序進程(這裏請讀者注意一下不同顏色所表示的不同進程,後文會與此保持一致)。

  (1)Launcher進程請求AMS創建根Activity。我們知道,在系統啓動過程中,會啓動SystemServer進程, AMS、PackageManagerService(後文簡稱PMS)也是在這個環節中啓動的,所以AMS是運行在SystemServer進程當中的。應用的根Activity會在AndroidManifest.xml文件中註冊,PMS解析出這些信息,並在Launcher中對這些包名、Activity路徑及名稱等信息進行封裝,當點擊快捷圖標時,Launcher會調用startActivity方法去啓動該圖標所對應的根Activity。然後在Luancher進程中通過層層調用,直到通過Binder方式實現IPC,流程就進入到AMS中,也就是SystemServer進程中。

  (2)AMS請求創建根Activity所在的進程。AMS收到Launcher進程啓動根Activity的請求後,會先判斷根Activity所在的進程是否已經創建過了,如果沒有創建過,則會向Zygote進程請求創建該進程,我們目前討論的情形就是根Activity所在進程沒有創建過的情況。我們知道,Zygote進程在啓動的時候,會作爲服務端創建一個名爲“zygote”的Socket,用於監聽AMS發起的創建新應用進程請求,所以此時流程進入到Zygote進程中。

  (3)Zygote進程fork出目標進程。Zygote收到AMS的請求後,會以fork的方式創建這個新的應用進程,此過程中會實例化一個ActivityThread對象,也就是一般所說的主線程,運行其入口main方法。

  (4)AMS調度應用進程創建和啓動根Activity。根Activity所在的應用程序進程被創建後,AMS在SystemServer進程中也經過層層調用,最終又通過Binder方式實現IPC,將啓動Activity的任務交給應用程序進程中的ApplicationThread本地代理,此後,流程進入到根Activity所在的應用程序進程中。這部分流程中,SystemServer中所做的工作主要是根Actifity創建和啓動前的一些準備工作,比如當前用戶權限等。

  (5)在應用進程中完成根Activity的創建和啓動。在這裏將創建根Activity實例、Applicaiton實例,調用各個生命週期方法,並將DecorView(佈局文件中的View會添加到DecorView中)添加到Window中顯示出來。 

       上文中涉及到系統啓動流程相關知識,比如Zygote、SystemServer、AMS、PMS 的啓動以及Zygote的功能,讀者不清楚的畫,最好先閱讀這篇文章:【系統之音】Android系統啓動篇

 

3、從Launcher到AMS

       先上UML序列圖 

       前面說過,點擊Luancher中的快捷圖標的時候,會通過startActivity啓動其對應的Activity,Launcher進程中的這部分流程源碼如下:

       Launcher.java的源碼路徑:/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

 1 //==========Launcher.java========
 2 private void startAppShortcutOrInfoActivity(View v) {
 3      ......
 4      boolean success = startActivitySafely(v, intent, item);
 5      ......
 6 }
 7 
 8 public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
 9      ......
10      startActivity(intent, optsBundle);
11      ......
12 }
13 
14 //===========Activity.java========
15 /**
16  * Launch a new activity.
17  * ......
18  */
19 @Override
20 public void startActivity(Intent intent, @Nullable Bundle options) {
21     if (options != null) {
22         startActivityForResult(intent, -1, options);
23     } else {
24         ......
25         startActivityForResult(intent, -1);
26     }
27 }
28 
29 public void startActivityForResult(...) {
30    if (mParent == null) { //表示當前根Activity還沒有創建
31             ......
32             Instrumentation.ActivityResult ar =
33                 mInstrumentation.execStartActivity(
34                     this, mMainThread.getApplicationThread(), mToken, this,
35                     intent, requestCode, options);
36             ......
37         }
38 }
39 
40 //===========Instrumentation.java==============
41 public ActivityResult execStartActivity(...){
42        ......
43        int result = ActivityManager.getService()
44                        .startActivity(whoThread, who.getBasePackageName(), intent,
45                                intent.resolveTypeIfNeeded(who.getContentResolver()),
46                                token, target != null ? target.mEmbeddedID : null,
47                                requestCode, 0, null, options); //代碼①
48        ......
49 }

通過上述代碼後,流程就從Launcher進程進入到AMS所在的SystemServer進程了, 這部分流程比較簡單,這裏就不做過多解釋了。這裏重點看一下代碼①處(第43行)的ActivityManager.getService():

 1 //=========ActivityManager.java=========
 2 public static IActivityManager getService() {
 3     return IActivityManagerSingleton.get();
 4 }
 5 private static final Singleton<IActivityManager> IActivityManagerSingleton =
 6         new Singleton<IActivityManager>() {
 7             @Override
 8             protected IActivityManager create() {
 9                 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
10                 final IActivityManager am = IActivityManager.Stub.asInterface(b);
11                 return am;
12             }
13         };
14 
15 //=================Singleton.java=========
16 /**
17  * Singleton helper class for lazily initialization.
18  * ......
19  */
20 public abstract class Singleton<T> {
21     private T mInstance;
22 
23     protected abstract T create();
24 
25     public final T get() {
26         synchronized (this) {
27             if (mInstance == null) {
28                 mInstance = create();
29             }
30             return mInstance;
31         }
32     }
33 }

ActivityManager.getService()這句代碼實際上就是通過單例模式獲取AMS在Launcher進程中的遠程代理,類似這樣的代碼實現在系統源碼種還是比較常見的。

 

4、從AMS到ApplicationThread(ActivityThread)

      先上UML序列圖:

        這一部分的啓動流程調用非常繁瑣,可謂是“峯迴路轉”,筆者在跟進其調用流程時差點昏厥了,大有“山重水複疑無路”的困惑,直到看到下面代碼:

1 final boolean realStartActivityLocked(...){
2       ......
3       app.thread.scheduleLaunchActivity(...); //代碼②
4       ......
5 }

此時又深感“柳暗花明又一村”了。ApplicationThread是ActivityThread中的一個內部類,也是應用程序進程中的一個服務(Stub),通過Binder方式對外提供服務:

1 //=======ActivityThread.java======
2 private class ApplicationThread extends IApplicationThread.Stub {
3       ......
4       public final void scheduleLaunchActivity(...){
5             ......
6       }
7       ......
8 }

這裏我們需要重點理解下圖中的模型:

       每個應用程序都運行在一個獨立的進程中(當然也可以聲明爲多個進程,這裏不做討論),不同進程之間內存等資源是不能直接共享的,只能通過Binder方式來和外界交互。這就好比系統像個大海,應用程序進程就像一座座孤島,而Binder就是孤島之間的橋樑或者船隻。上圖中模擬了應用程序進程與SystemServer進程的交互方式,應用程序進程持有了SystemServer進程中AMS/WMS等系統服務的遠程代理Proxy,通過這個Proxy來調用SystemServer進程中的系統服務;SystemServer進程中也持有了應用程序進程中的ApplicationThread的遠程代理Proxy,通過這個Proxy來調用應用程序進程中的方法。

       代碼②處的app.thread就是ApplicationThread在SystemServer端的遠程代理(Proxy),正式通過這個遠程代理調用根Activity所在應用程序進程中的相關方法的從這裏開始,流程就進入到目標應用程序進程了。

       由於該部分又繁瑣,又沒有涉及到直接創建和啓動Activity的代碼,所以這裏就不貼代碼了。對於這一部分的流程,個人建議讀者沒有必要太糾結細節,知道其大概做了些什麼就夠了。

 

5、在應用程序進程中創建和啓動根Activity

       先看看ActivityThread類主要結構

       ActivityThread一般被稱作主線程(當然它不是真正的線程),它包含兩個很重要的內部類,ApplicationThread(前面已經介紹過了)和H。這個H是Handler的子類,擁有主線程的looper,所以其Callback的回調函數handleMessage運行在主現在當中,所以這個H類的作用其實就是將線程切換到主線程。

       我們結合上圖來看看如下源碼:

 1 //=======ActivityThread.java======
 2 private class ApplicationThread extends IApplicationThread.Stub {
 3       ......
 4       public final void scheduleLaunchActivity(...){
 5             ActivityClientRecord r = new ActivityClientRecord();
 6             ......
 7             r.intent = intent;
 8             ......
 9             sendMessage(H.LAUNCH_ACTIVITY, r);
10       }
11       ......
12 }
13 
14 private void sendMessage(int what, Object obj) {
15     sendMessage(what, obj, 0, 0, false);
16 }
17 
18 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
19     ......
20     Message msg = Message.obtain();
21     msg.what = what;
22     msg.obj = obj;
23     msg.arg1 = arg1;
24     msg.arg2 = arg2;
25     ......
26     mH.sendMessage(msg);
27 }
28 
29 final H mH = new H();
30 private class H extends Handler {
31     public static final int LAUNCH_ACTIVITY = 100;
32     public void handleMessage(Message msg) {
33         switch (msg.what) {
34                 case LAUNCH_ACTIVITY: {
35                       ......
36                       handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//代碼③
37                       ......
38                 }
39     }
40      ......
41 }

這樣就明確了,此時的流程,又由ApplicationThread經過Handler進入到了主線程(ActivityThread)中了。

從代碼③處開始,流程就由主線程ActivityThread來處理了,還是先上UML序列圖:

 參照該圖和如下源碼,來看看應用程序進程是如何創建和啓動Activity的:

 1 //=======ActivityThread.java=======
 2 private void handleLaunchActivity(...){
 3      ......
 4      WindowManagerGlobal.initialize();//代碼④
 5      ......
 6      Activity a = performLaunchActivity(r, customIntent);//代碼⑤
 7      if (a != null) {
 8          handleResumeActivity(...);//代碼⑫
 9      }
10      ......
11 }

代碼④,其作用是通過單例模式獲取一個WMS在應用程序進程中的遠程代理Proxy,我們知道,後面Activity中setContentView加載的layout文件,就需要通過WMS添加到Window中來顯示。該方法代碼比較簡單:

 1 //========WindowManagerGlobal.java======
 2 ......
 3 private static IWindowManager sWindowManagerService;
 4 ......
 5 public static void initialize() {
 6     getWindowManagerService();
 7 }
 8 ......
 9 public static IWindowManager getWindowManagerService() {
10     synchronized (WindowManagerGlobal.class) {
11         if (sWindowManagerService == null) {
12             sWindowManagerService = IWindowManager.Stub.asInterface(
13                     ServiceManager.getService("window"));
14             ......
15         }
16         return sWindowManagerService;
17     }
18 }

進入到代碼⑤處:

 1 //===========ActivityThread.java=======
 2 private Activity performLaunchActivity(...){
 3         ......
 4         Activity activity = null;
 5         try {
 6             java.lang.ClassLoader cl = appContext.getClassLoader();
 7             activity = mInstrumentation.newActivity(
 8                     cl, component.getClassName(), r.intent);//代碼⑥
 9             ......
10         } catch (Exception e) {
11             ......
12         }
13         try {
14             Application app = r.packageInfo.makeApplication(false, mInstrumentation);//代碼⑦
15               ......
16               activity.attach(...);
17               ......
18              if (r.isPersistable()) {
19                     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); //代碼⑩-1
20                 } else {
21                     mInstrumentation.callActivityOnCreate(activity, r.state);//代碼⑩-2
22                 }
23               ......
24                 if (!r.activity.mFinished) {
25                     activity.performStart();//代碼⑪
26                     ......
27                 }
28               ......
29              } catch (Exception e) {
30             ......
31         }
32         ......
33 }

代碼⑥處,以ClassLoader的方式創建Activity實例:

 1 //================Instrumentation.java=====
 2 /**
 3  * Perform instantiation of the process's {@link Activity} object.
 4  * ......
 5  * @return The newly instantiated Activity object.
 6  */
 7 public Activity newActivity(ClassLoader cl, String className,
 8         Intent intent)
 9         throws InstantiationException, IllegalAccessException,
10         ClassNotFoundException {
11     return (Activity)cl.loadClass(className).newInstance();
12 }

從代碼⑦處深入,該代碼的作用在於處理Application相關的業務:

 1 //=========LoadedApk.java=========
 2 public Application makeApplication(...){
 3     if (mApplication != null) {
 4             return mApplication;
 5         }
 6      ......
 7      Application app = null;
 8      ......
 9         try {
10             java.lang.ClassLoader cl = getClassLoader();
11             ......
12             app = mActivityThread.mInstrumentation.newApplication(
13                     cl, appClass, appContext); //代碼⑧
14             ......
15         } catch (Exception e) {
16            ......
17         }
18         mActivityThread.mAllApplications.add(app);
19         mApplication = app;
20         if (instrumentation != null) {
21             try {
22                 instrumentation.callApplicationOnCreate(app);//代碼⑨
23             } catch (Exception e) {
24                 ......
25             }
26         }
27         ......
28 }

代碼⑧處,也是以ClassLoader方式創建Application實例:

 1 //================Instrumentaion.java=========
 2 /**
 3  * Perform instantiation of the process's {@link Application} object.
 4  * ......
 5  * @return The newly instantiated Application object.
 6  */
 7 public Application newApplication(ClassLoader cl, String className, Context context)
 8         throws InstantiationException, IllegalAccessException,
 9         ClassNotFoundException {
10     return newApplication(cl.loadClass(className), context);
11 }
12 
13 /**
14  * Perform instantiation of the process's {@link Application} object.
15  * ......
16  * @return The newly instantiated Application object.
17  */
18 static public Application newApplication(Class<?> clazz, Context context)
19         throws InstantiationException, IllegalAccessException,
20         ClassNotFoundException {
21     Application app = (Application)clazz.newInstance();
22     app.attach(context);
23     return app;
24 }

代碼⑨處,調用Application的onCreate方法,在自定義的Application中,重寫的onCreate方法開始執行:

 1 //=============LoadedApk.java========
 2 /**
 3  * Perform calling of the application's {@link Application#onCreate} method.
 4  * ......
 5  * @param app The application being created.
 6  */
 7 public void callApplicationOnCreate(Application app) {
 8     app.onCreate();
 9 }
10 
11 //=========Application.java========
12 @CallSuper
13 public void onCreate() {
14 }

代碼⑩(代碼⑩-1或代碼⑩-2)中,執行Activity的onCreate方法,根Activity中的onCreate方法執行:

 1 //==============Instrumentation.java========
 2 /**
 3  * Perform calling of an activity's {@link Activity#onCreate} method.
 4  * ......
 5  */
 6 public void callActivityOnCreate(Activity activity, Bundle icicle) {
 7     prePerformCreate(activity);
 8     activity.performCreate(icicle);
 9     postPerformCreate(activity);
10 }
11 /**
12  * Perform calling of an activity's {@link Activity#onCreate} method.
13  * ......
14  */
15 public void callActivityOnCreate(Activity activity, Bundle icicle,
16         PersistableBundle persistentState) {
17     prePerformCreate(activity);
18     activity.performCreate(icicle, persistentState);
19     postPerformCreate(activity);
20 }
21 
22 //==========Activity.java========
23 final void performCreate(Bundle icicle) {
24     performCreate(icicle, null);
25 }
26 final void performCreate(Bundle icicle, PersistableBundle p
27     ......
28     if (persistentState != null) {
29         onCreate(icicle, persistentState);
30     } else {
31         onCreate(icicle);
32     }
33     ......
34 }
35 
36 public void onCreate(@Nullable Bundle savedInstanceState,
37         @Nullable PersistableBundle persistentState) {
38     onCreate(savedInstanceState);
39 }
40 
41 @MainThread
42 @CallSuper
43 protected void onCreate(@Nullable Bundle savedInstanceState) {
44     ......
45 }
代碼⑪開始執行Activity的onStart方法,根Activity的onStart方法開始執行:
 1 //======Activity.java======
 2 final void performStart() {
 3     ......
 4     mInstrumentation.callActivityOnStart(this);
 5     ......
 6 }
 7 
 8 //=========Instrumentation.java=========
 9 /**
10  * Perform calling of an activity's {@link Activity#onStart} method.
11  * ......
12  */
13 public void callActivityOnStart(Activity activity) {
14     activity.onStart();
15 }
16 
17 //======Activity.java======
18 @CallSuper
19 protected void onStart() {
20     ......
21 }
代碼⑫的handleResumeActivity方法用於處理resume相關的業務:
 1 //========ActivityThread.java======
 2 final void handleResumeActivity(...){
 3       ......
 4       r = performResumeActivity(token, clearHide, reason);//代碼⑬
 5       ......
 6       //如下過程將DecorView添加到窗口中 代碼段⑯
 7       r.window = r.activity.getWindow(); //PhoneWindow實例
 8       View decor = r.window.getDecorView(); //DecorView實例
 9       decor.setVisibility(View.INVISIBLE);
10       ViewManager wm = a.getWindowManager();
11       WindowManager.LayoutParams l = r.window.getAttributes();
12       a.mDecor = decor;
13       ......
14       ViewRootImpl impl = decor.getViewRootImpl();
15       ......
16       wm.addView(decor, l);
17       ......
18 }

深入代碼⑬中:

 1 //======ActivityThread=======
 2 public final ActivityClientRecord performResumeActivity(...){
 3       ......
 4       r.activity.performResume();
 5       ......
 6 }
 7 
 8 //======Activity.java=====
 9 final void performResume() {
10      performRestart();//代碼⑭
11      ......
12      mInstrumentation.callActivityOnResume(this);//代碼⑮
13      ......
14 }

代碼⑭用於處理reStart相關的業務,當前場景是新創建根Activity,所以不會走這個流程;如果是從其它界面回退到這個activity,就會走調用onRestart和onStart的流程:

 1 //===========Activity.java========
 2 final void performRestart() {
 3      ......
 4      if (mStopped) {
 5           mStopped = false;
 6           ......
 7           mInstrumentation.callActivityOnRestart(this);
 8           ......
 9           performStart();
10      }
11 }
12 
13 //============Instrumentation.java===========
14 /**
15  * Perform calling of an activity's {@link Activity#onRestart} method.
16  * ......
17  * @param activity The activity being restarted.
18  */
19 public void callActivityOnRestart(Activity activity) {
20     activity.onRestart();
21 }
22 
23 //===========Activity.java===========
24 @CallSuper
25 protected void onRestart() {
26     mCalled = true;
27 }
28 
29 final void performStart() {
30      ......
31      mInstrumentation.callActivityOnStart(this);
32      ......
33 }
34 
35 //============Instrumentation.java==========
36 /**
37  * Perform calling of an activity's {@link Activity#onStart} method.
38  *  ......
39  * @param activity The activity being started.
40  */
41 public void callActivityOnStart(Activity activity) {
42     activity.onStart();
43 }
44 //==============Activity.java============
45 @CallSuper
46 protected void onStart() {
47    ......
48 }

代碼⑮處調用acitvity的onResume方法,這樣一來根Activity的onResume回調方法就執行了:

 1 //========Instrumentation.java=========
 2 /**
 3  * Perform calling of an activity's {@link Activity#onResume} method.
 4  *  ......
 5  * @param activity The activity being resumed.
 6  */
 7 public void callActivityOnResume(Activity activity) {
 8     ......
 9     activity.onResume();
10     ......
11 }
12 
13 @CallSuper
14 protected void onResume() {
15     ......
16 }

代碼段⑯(對應第7~16行)的作用在於將DecorView添加到Window,並完成界面的繪製流程。我們知道,根Activity在onCreate生命週期回調方法中會通過setContentView方法加載layout佈局文件,將其加入到DecorView中,繪製部分詳情可以閱讀【【朝花夕拾】Android自定義View篇之(一)View繪製流程】。

       這樣,應用程序進程就完成了根Activity的創建和啓動,界面也完成了顯示。從上面的UML圖和源碼分析,可以發現這部分筆者是按照Activity的生命週期爲主線來介紹的,實際上讀者完全可以結合Activity的生命週期來理解和記憶這部分的主要流程。下圖再次總結了這部分的主要流程:

 

       想必讀者應該對第4~7步的生命週期順序非常熟悉了。需要注意的是,第2和第3步可能會和我們平時的認知有些出入,實際上Activity的實例比Application的實例要更早創建。第1和第8步是關於圖形界面顯示的,也需要重點關心。

6、其它場景啓動流程

       到目前爲止,從Laucher中點擊一個快捷圖標來啓動根Activity的整個流程就介紹完畢了,這個場景搞清楚了,其它場景就不在話下了。比如,從Launcher中啓動一個應用程序進程已經啓動的應用的根Activity,就在上述流程基礎上少了Zytote創建應用程序進程這一步,如下圖:

 比如,應用程序內部啓動另外一個新Activity時,就只需要考慮應用程序進程和SystemSever兩個進程,如下圖:

還有從其它應用中啓動指定某另外應用中的Activity的場景和從Launcher啓動的流程類似;再次打開一個已經啓動的Activity,就無需走create流程,而是走onRestart-onStart-onResume生命週期流程,等等,這裏就不一一列舉了。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章