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进阶解密》