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

 //==========Launcher.java========
private void startAppShortcutOrInfoActivity(View v) {
......
boolean success = startActivitySafely(v, intent, item);
......
} public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
......
startActivity(intent, optsBundle);
......
} //===========Activity.java========
/**
* Launch a new activity.
* ......
*/
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
......
startActivityForResult(intent, -1);
}
} public void startActivityForResult(...) {
if (mParent == null) { //表示当前根Activity还没有创建
......
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
......
}
} //===========Instrumentation.java==============
public ActivityResult execStartActivity(...){
......
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options); //代码①
......
}

通过上述代码后,流程就从Launcher进程进入到AMS所在的SystemServer进程了, 这部分流程比较简单,这里就不做过多解释了。这里重点看一下代码①处(第43行)的ActivityManager.getService():

 //=========ActivityManager.java=========
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
}; //=================Singleton.java=========
/**
* Singleton helper class for lazily initialization.
* ......
*/
public abstract class Singleton<T> {
private T mInstance; protected abstract T create(); public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}

ActivityManager.getService()这句代码实际上就是通过单例模式获取AMS在Launcher进程中的远程代理,类似这样的代码实现在系统源码种还是比较常见的。

4、从AMS到ApplicationThread(ActivityThread)

先上UML序列图:

这一部分的启动流程调用非常繁琐,可谓是“峰回路转”,笔者在跟进其调用流程时差点昏厥了,大有“山重水复疑无路”的困惑,直到看到下面代码:

 final boolean realStartActivityLocked(...){
......
app.thread.scheduleLaunchActivity(...); //代码②
......
}

此时又深感“柳暗花明又一村”了。ApplicationThread是ActivityThread中的一个内部类,也是应用程序进程中的一个服务(Stub),通过Binder方式对外提供服务:

 //=======ActivityThread.java======
private class ApplicationThread extends IApplicationThread.Stub {
......
public final void scheduleLaunchActivity(...){
......
}
......
}

这里我们需要重点理解下图中的模型:

每个应用程序都运行在一个独立的进程中(当然也可以声明为多个进程,这里不做讨论),不同进程之间内存等资源是不能直接共享的,只能通过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类的作用其实就是将线程切换到主线程。

我们结合上图来看看如下源码:

 //=======ActivityThread.java======
private class ApplicationThread extends IApplicationThread.Stub {
......
public final void scheduleLaunchActivity(...){
ActivityClientRecord r = new ActivityClientRecord();
......
r.intent = intent;
......
sendMessage(H.LAUNCH_ACTIVITY, r);
}
......
} 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;
......
mH.sendMessage(msg);
} final H mH = new H();
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
......
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//代码③
......
}
}
......
}

这样就明确了,此时的流程,又由ApplicationThread经过Handler进入到了主线程(ActivityThread)中了。

从代码③处开始,流程就由主线程ActivityThread来处理了,还是先上UML序列图:

参照该图和如下源码,来看看应用程序进程是如何创建和启动Activity的:

 //=======ActivityThread.java=======
private void handleLaunchActivity(...){
......
WindowManagerGlobal.initialize();//代码④
......
Activity a = performLaunchActivity(r, customIntent);//代码⑤
if (a != null) {
handleResumeActivity(...);//代码⑫
}
......
}

代码④,其作用是通过单例模式获取一个WMS在应用程序进程中的远程代理Proxy,我们知道,后面Activity中setContentView加载的layout文件,就需要通过WMS添加到Window中来显示。该方法代码比较简单:

 //========WindowManagerGlobal.java======
......
private static IWindowManager sWindowManagerService;
......
public static void initialize() {
getWindowManagerService();
}
......
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
......
}
return sWindowManagerService;
}
}

进入到代码⑤处:

 //===========ActivityThread.java=======
private Activity performLaunchActivity(...){
......
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);//代码⑥
......
} catch (Exception e) {
......
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//代码⑦
......
activity.attach(...);
......
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); //代码⑩-1
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);//代码⑩-2
}
......
if (!r.activity.mFinished) {
activity.performStart();//代码⑪
......
}
......
} catch (Exception e) {
......
}
......
}

代码⑥处,以ClassLoader的方式创建Activity实例:

 //================Instrumentation.java=====
/**
* Perform instantiation of the process's {@link Activity} object.
* ......
* @return The newly instantiated Activity object.
*/
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}

从代码⑦处深入,该代码的作用在于处理Application相关的业务:

 //=========LoadedApk.java=========
public Application makeApplication(...){
if (mApplication != null) {
return mApplication;
}
......
Application app = null;
......
try {
java.lang.ClassLoader cl = getClassLoader();
......
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext); //代码⑧
......
} catch (Exception e) {
......
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);//代码⑨
} catch (Exception e) {
......
}
}
......
}

代码⑧处,也是以ClassLoader方式创建Application实例:

 //================Instrumentaion.java=========
/**
* Perform instantiation of the process's {@link Application} object.
* ......
* @return The newly instantiated Application object.
*/
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
} /**
* Perform instantiation of the process's {@link Application} object.
* ......
* @return The newly instantiated Application object.
*/
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}

代码⑨处,调用Application的onCreate方法,在自定义的Application中,重写的onCreate方法开始执行:

 //=============LoadedApk.java========
/**
* Perform calling of the application's {@link Application#onCreate} method.
* ......
* @param app The application being created.
*/
public void callApplicationOnCreate(Application app) {
app.onCreate();
} //=========Application.java========
@CallSuper
public void onCreate() {
}

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

 //==============Instrumentation.java========
/**
* Perform calling of an activity's {@link Activity#onCreate} method.
* ......
*/
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
/**
* Perform calling of an activity's {@link Activity#onCreate} method.
* ......
*/
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
} //==========Activity.java========
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle p
......
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
......
} public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
} @MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
......
}
代码⑪开始执行Activity的onStart方法,根Activity的onStart方法开始执行:
 //======Activity.java======
final void performStart() {
......
mInstrumentation.callActivityOnStart(this);
......
} //=========Instrumentation.java=========
/**
* Perform calling of an activity's {@link Activity#onStart} method.
* ......
*/
public void callActivityOnStart(Activity activity) {
activity.onStart();
} //======Activity.java======
@CallSuper
protected void onStart() {
......
}
代码⑫的handleResumeActivity方法用于处理resume相关的业务:
 //========ActivityThread.java======
final void handleResumeActivity(...){
......
r = performResumeActivity(token, clearHide, reason);//代码⑬
......
//如下过程将DecorView添加到窗口中 代码段⑯
r.window = r.activity.getWindow(); //PhoneWindow实例
View decor = r.window.getDecorView(); //DecorView实例
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
......
ViewRootImpl impl = decor.getViewRootImpl();
......
wm.addView(decor, l);
......
}

深入代码⑬中:

 //======ActivityThread=======
public final ActivityClientRecord performResumeActivity(...){
......
r.activity.performResume();
......
} //======Activity.java=====
final void performResume() {
performRestart();//代码⑭
......
mInstrumentation.callActivityOnResume(this);//代码⑮
......
}

代码⑭用于处理reStart相关的业务,当前场景是新创建根Activity,所以不会走这个流程;如果是从其它界面回退到这个activity,就会走调用onRestart和onStart的流程:

 //===========Activity.java========
final void performRestart() {
......
if (mStopped) {
mStopped = false;
......
mInstrumentation.callActivityOnRestart(this);
......
performStart();
}
} //============Instrumentation.java===========
/**
* Perform calling of an activity's {@link Activity#onRestart} method.
* ......
* @param activity The activity being restarted.
*/
public void callActivityOnRestart(Activity activity) {
activity.onRestart();
} //===========Activity.java===========
@CallSuper
protected void onRestart() {
mCalled = true;
} final void performStart() {
......
mInstrumentation.callActivityOnStart(this);
......
} //============Instrumentation.java==========
/**
* Perform calling of an activity's {@link Activity#onStart} method.
* ......
* @param activity The activity being started.
*/
public void callActivityOnStart(Activity activity) {
activity.onStart();
}
//==============Activity.java============
@CallSuper
protected void onStart() {
......
}

代码⑮处调用acitvity的onResume方法,这样一来根Activity的onResume回调方法就执行了:

 //========Instrumentation.java=========
/**
* Perform calling of an activity's {@link Activity#onResume} method.
* ......
* @param activity The activity being resumed.
*/
public void callActivityOnResume(Activity activity) {
......
activity.onResume();
......
} @CallSuper
protected void onResume() {
......
}

代码段⑯(对应第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生命周期流程,等等,这里就不一一列举了。

最新文章

  1. Java 泛型约束
  2. hdu3966 树链剖分+成段更新
  3. Linux文件管理系统
  4. MSP430常见问题之复位系统类
  5. 用maven在eclipse用spring建javaweb工程(一)
  6. [算法题] Remove Element
  7. Southwestern Europe Regional Contest 2014 题解
  8. asp.net core封装layui组件示例分享
  9. java数组:去重,增加,删除元素
  10. Python打包工具setuptools的使用
  11. SQL CE 和 SQLite数据库对比测试
  12. 五一培训 DAY1
  13. 推理机Jess,Racer,Jena
  14. C-Lodop提示“有窗口已打开,先关闭它(持续如此请刷新页面)!”
  15. Lambda表达式详解(例子详解)(转自:http://blog.csdn.net/damon316/article/details/51734661)
  16. Android退出所有Activity最优雅的方式
  17. Mongodb副本集+分片集群环境部署记录
  18. SpringBoot之退出服务(exit)时调用自定义的销毁方法
  19. Map遍历的几种方法
  20. Python之Cookielib

热门文章

  1. LGV定理
  2. 我们通常这样使用Linux弱口令检测!
  3. 前端学习(十二):CSS排版
  4. 04爬取拉勾网Python岗位分析报告
  5. 启动扫描闪退,因为忘了在manifest里申请手机镜头使用许可了。
  6. rpm -ivh vsftpd-3.0.2-22.el7.x86_64.rpm出现error: open of vsftpd-3.0.2-22.el7.x86_64.rpm failed: No such file or directory的解决方法
  7. JavaScript Symbol对象
  8. 代码规范、API设计等规范
  9. idea中运行Tomcat后控制台出现乱码(统一设置成UTF-8)
  10. hdu6787(骰子+往回推的传输带问通过方案,dp)