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生命週期流程,等等,這裡就不一一列舉了。