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創建和啟動前的一些准備工作,比如判單當前用戶權限,判斷目標進程是否存在,判斷activity是否已經創建,判斷啟動模式,判斷是否注冊等。
(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到應用程序進程
先上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、其它Activity啟動場景流程
到目前為止,從Laucher中點擊一個快捷圖標來啟動根Activity的整個流程就介紹完畢了,這個場景搞清楚了,其它場景就不在話下了。比如,從Launcher中啟動一個應用程序進程已經啟動的應用的根Activity,就在上述流程基礎上少了Zytote創建應用程序進程這一步,如下圖:
比如,應用程序內部啟動另外一個新Activity時,就只需要考慮應用程序進程和SystemSever兩個進程,如下圖:
還有從其它應用中啟動指定某另外應用中的Activity的場景和從Launcher啟動的流程類似;再次打開一個已經啟動的Activity,就無需走create流程,而是走onRestart-onStart-onResume生命周期流程,等等,這里就不一一列舉了。
本文已經盡可能地包含了完整的流程,但同時力求簡潔易懂,摒棄大量具體細節,只抽取關鍵流程。盡管如此,但是這部分內容確實比較復雜,還是花了這么長的篇幅,感謝讀者的耐心閱讀。由於筆者水平有限,有些描述不准確或者不妥之處,請讀者朋友不吝賜教,感謝!
參考資料
【朝花夕拾】Android自定義View篇之(一)View繪制流程
劉望舒《Android進階解密》