APP和activity启动流程

整个 startActivity 的流程分为 3 大部分,也涉及 3 个进程之间的交互:

ActivityA --> ActivityManagerService(简称 AMS)

ActivityManagerService --> ApplicationThread

ApplicationThread --> Activity

ActivityA --> ActivityManagerService 阶段

这一过程并不复杂,用一张图表示具体过程如下:

Activity 的 startActivity

最终调用了 startActivityForResult 方法,传入的 -1 表示不需要获取 startActivity 的结果。

Activity 的 startActivityForResult

startActivityForResult 也很简单,调用 Instrumentation.execStartActivity 方法。剩下的交给 Instrumentation 类去处理。

解释说明:

Instrumentation 类主要用来监控应用程序与系统交互。

蓝框中的 mMainThread 是 ActivityThread 类型,ActivityThread 可以理解为一个进程,在这就是 A 所在的进程。

通过 mMainThread 获取一个 ApplicationThread 的引用,这个引用就是用来实现进程间通信的,具体来说就是 AMS 所在系统进程通知应用程序进程进行的一系列操作。

app进程通过ActivityManager.getService (高版本)或者 ActivityManagerNative.getDefault(低版本)返回的IActivityManager来调用系统进程AMS中的方法。该IActivityManager是AMS在app进程的binder代理对象

同样,系统进程通过ProcessRecord.IApplicationThread调用app进程相关方法。IApplicationThread是系统进程持有的app进程中ApplicationThread的Binder代理对象。

AMS通过binder代理调用到ApplicationThread(ActivityThread的内部类)中的方法后,通过主线程(ActivityThread中的main方法)中开启的handler消息轮询来通知主线程调用相关方法。主线程的相关声明周期方法的具体实现会委托给Instrumentation类实现,在Instrumentation类中,会调用具体组件的相关生命周期方法。

Activity启动之前的一些事情

init进程:init是所有linux程序的起点,是Zygote的父进程。解析init.rc孵化出Zygote进程。

Zygote进程:Zygote是所有Java进程的父进程,所有的App进程都是由Zygote进程fork生成的。

SystemServer进程:System Server是Zygote孵化的第一个进程。SystemServer负责启动和管理整个Java framework,包含AMS,PMS等服务。

Launcher:Zygote进程孵化的第一个App进程是Launcher。

1.init进程是什么?

Android是基于linux系统的,手机开机之后,linux内核进行加载。加载完成之后会启动init进程。

init进程会启动ServiceManager,孵化一些守护进程,并解析init.rc孵化Zygote进程。

2.Zygote进程是什么?

所有的App进程都是由Zygote进程fork生成的,包括SystemServer进程。Zygote初始化后,会注册一个等待接受消息的socket,OS层会采用socket进行IPC通信。

3.为什么是Zygote来孵化进程,而不是新建进程呢?

每个应用程序都是运行在各自的Dalvik虚拟机中,应用程序每次运行都要重新初始化和启动虚拟机,这个过程会耗费很长时间。Zygote会把已经运行的虚拟机的代码和内存信息共享,起到一个预加载资源和类的作用,从而缩短启动时间。

Activity启动阶段

涉及到的概念

进程:Android系统为每个APP分配至少一个进程

IPC:跨进程通信,Android中采用Binder机制。

涉及到的类

ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ActivitySupervisor:管理 activity 任务栈

ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。

ApplicationThread:用来实现AMS和ActivityThread之间的交互。

ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理与ActivityThread进行通信的。

IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能

AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。

AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。

AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。

Instrumentation:仪表盘,负责调用Activity和Application生命周期。测试用到这个类比较多。

ActivityStackSupervisor

负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。其中,mHomeStack管理的是Launcher相关的Activity栈;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈。

ActivityThread.java  路径位于:\frameworks\base\core\java\android\app\ActivityThread.java

说明:该类为应用程序(即APK包)所对应进程(一个进程里可能有多个应用程序)的主线程类,即我们通常所说的UI线程。

一个ActivityThread类对应于一个进程。最重要的是,每个应用程序的入口是该类中的static main()函数 。

Instrumentation.java路径位于 :\frameworks\base\core\java\android\app\ActivityThread.java

说明:该类用于具体操作某个Activity的功能----单向(oneway)调用AMS以及统计、测量该应用程序的所有开销。

一个Instrumentation类对应于一个进程。每个Activity内部都有一个该Instrumentation对象的引用。

举个例子吧。

我们将我们应用程序比作一个四合院,那么Activity对应于四合院的人,ActivithThread对应于院子的主人----管理所有人,

Instrumentation对应于管家------受气的命,接受来自人(Activity/ActivithThread)的命令 ,去单向(oneway)调用AMS 。

ApplicationThread类是ActivityThread的内部类:

说明:该类是一个Binder类,即可实现跨进程通信。主要用于接受从AMS传递过来的消息,继而做相应处理。

具体流程

Launcher:Launcher通知AMS要启动activity。

startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity

AMS:PMS的resoveIntent验证要启动activity是否匹配。

如果匹配,通过ApplicationThread发消息给Launcher所在的主线程,暂停当前Activity(Launcher);

暂停完,在该activity还不可见时,通知AMS,根据要启动的Activity配置ActivityStack。然后判断要启动的Activity进程是否存在?

存在:发送消息LAUNCH_ACTIVITY给需要启动的Activity主线程,执行handleLaunchActivity

不存在:通过socket向zygote请求创建进程。进程启动后,ActivityThread.attach

判断Application是否存在,若不存在,通过LoadApk.makeApplication创建一个。在主线程中通过thread.attach方法来关联ApplicationThread。

在通过ActivityStackSupervisor来获取当前需要显示的ActivityStack。

继续通过ApplicationThread来发送消息给主线程的Handler来启动Activity(handleLaunchActivity)。

handleLauchActivity:调用了performLauchActivity,里边Instrumentation生成了新的activity对象,继续调用activity生命周期。

IPC过程:

双方都是通过对方的代理对象来进行通信。

1.app和AMS通信:app通过本进程的AMP和AMS进行Binder通信

2.AMS和新app通信:通过ApplicationThreadProxy来通信,并不直接和ActivityThread通信

参考函数流程

Activity启动流程(从Launcher开始):

第一阶段:Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

Launcher.startActivitySafely //首先Launcher发起启动Activity的请求

Activity.startActivity

Activity.startActivityForResult

Instrumentation.execStartActivity //交由Instrumentation代为发起请求

ActivityManager.getService().startActivity //通过IActivityManagerSingleton.get()得到一个AMP代理对象

ActivityManagerProxy.startActivity //通过AMP代理通知AMS启动activity

第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

ActivityManagerService.startActivity

ActivityManagerService.startActivityAsUser

ActivityStackSupervisor.startActivityMayWait

ActivityStackSupervisor.startActivityLocked :检查有没有在AndroidManifest中注册

ActivityStackSupervisor.startActivityUncheckedLocked

ActivityStack.startActivityLocked :判断是否需要创建一个新的任务来启动Activity。

ActivityStack.resumeTopActivityLocked :获取栈顶的activity,并通知Launcher应该pause掉这个Activity以便启动新的activity。

ActivityStack.startPausingLocked

ApplicationThreadProxy.schedulePauseActivity

第三阶段:pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

ApplicationThread.schedulePauseActivity

ActivityThread.queueOrSendMessage

H.handleMessage

ActivityThread.handlePauseActivity

ActivityManagerProxy.activityPaused

第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程)

ActivityManagerService.activityPaused

ActivityStack.activityPaused

ActivityStack.completePauseLocked

ActivityStack.resumeTopActivityLocked

ActivityStack.startSpecificActivityLocked

ActivityManagerService.startProcessLocked

Process.start //在这里创建了新进程,新的进程会导入ActivityThread类,并执行它的main函数

第五阶段:创建ActivityThread实例,执行一些初始化操作,并绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

ActivityThread.main

ActivityThread.attach(false) //声明不是系统进程

ActivityManagerProxy.attachApplication

第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

ActivityManagerService.attachApplication //AMS绑定本地ApplicationThread对象,后续通过ApplicationThreadProxy来通信。

ActivityManagerService.attachApplicationLocked

ActivityStack.realStartActivityLocked //真正要启动Activity了!

ApplicationThreadProxy.scheduleLaunchActivity //AMS通过ATP通知app进程启动Activity

第七阶段:加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

ApplicationThread.scheduleLaunchActivity //ApplicationThread发消息给AT

ActivityThread.queueOrSendMessage

H.handleMessage //AT的Handler来处理接收到的LAUNCH_ACTIVITY的消息

ActivityThread.handleLaunchActivity

ActivityThread.performLaunchActivity

Instrumentation.newActivity //调用Instrumentation类来新建一个Activity对象

Instrumentation.callActivityOnCreate

MainActivity.onCreate

ActivityThread.handleResumeActivity

AMP.activityResumed

AMS.activityResumed(AMS进程)

一:开始请求执行启动Activity

MyActivity.startActivity() 

Activity.startActivity() 

Activity.startActivityForResult 

Instrumentation.execStartActivty 

ActivityManagerNative.getDefault().startActivityAsUser() 

二:ActivityManagerService接收启动Activity的请求

ActivityManagerService.startActivity() 

ActvityiManagerService.startActivityAsUser() 

ActivityStackSupervisor.startActivityMayWait() 

ActivityStackSupervisor.startActivityLocked() 

ActivityStackSupervisor.startActivityUncheckedLocked() 

ActivityStackSupervisor.startActivityLocked() 

ActivityStackSupervisor.resumeTopActivitiesLocked() 

ActivityStackSupervisor.resumeTopActivityInnerLocked() 

三:执行栈顶Activity的onPause方法

ActivityStack.startPausingLocked() 

IApplicationThread.schudulePauseActivity() 

ActivityThread.sendMessage() 

ActivityThread.H.sendMessage(); 

ActivityThread.H.handleMessage() 

ActivityThread.handlePauseActivity() 

ActivityThread.performPauseActivity() 

Activity.performPause() 

Activity.onPause() 

ActivityManagerNative.getDefault().activityPaused(token) 

ActivityManagerService.activityPaused() 

ActivityStack.activityPausedLocked() 

ActivityStack.completePauseLocked() 

ActivityStack.resumeTopActivitiesLocked() 

ActivityStack.resumeTopActivityLocked() 

ActivityStack.resumeTopActivityInnerLocked() 

ActivityStack.startSpecificActivityLocked 

四:启动Activity所属的应用进程

关于如何启动应用进程,前面的一篇文章已经做了介绍,可参考: android源码解析之(十一)–>应用进程启动流程 这里在简单的介绍一下

ActivityManagerService.startProcessLocked() 

Process.start() 

ActivityThread.main() 

ActivityThread.attach() 

ActivityManagerNative.getDefault().attachApplication() 

ActivityManagerService.attachApplication() 

五:执行启动Acitivity

ActivityStackSupervisor.attachApplicationLocked() 

ActivityStackSupervisor.realStartActivityLocked() 

IApplicationThread.scheduleLauncherActivity() 

ActivityThread.sendMessage() 

ActivityThread.H.sendMessage() 

ActivityThread.H.handleMessage() 

ActivityThread.handleLauncherActivity() 

ActivityThread.performLauncherActivity() 

Instrumentation.callActivityOnCreate() 

Activity.onCreate() 

ActivityThread.handleResumeActivity() 

ActivityThread.performResumeActivity() 

Activity.performResume() 

Instrumentation.callActivityOnResume() 

Activity.onResume() 

ActivityManagerNative.getDefault().activityResumed(token) 

六:栈顶Activity执行onStop方法

Looper.myQueue().addIdleHandler(new Idler()) 

Idler.queueIdle() 

ActivityManagerNative.getDefault().activityIdle() 

ActivityManagerService.activityIdle() 

ActivityStackSupervisor.activityIdleInternalLocked() 

ActivityStack.stopActivityLocked() 

IApplicationThread.scheduleStopActivity() 

ActivityThread.scheduleStopActivity() 

ActivityThread.sendMessage() 

ActivityThread.H.sendMessage() 

ActivityThread.H.handleMessage() 

ActivityThread.handleStopActivity() 

ActivityThread.performStopActivityInner() 

ActivityThread.callCallActivityOnSaveInstanceState() 

Instrumentation.callActivityOnSaveInstanceState() 

Activity.performSaveInstanceState() 

Activity.onSaveInstanceState() 

Activity.performStop() 

Instrumentation.callActivityOnStop() 

Activity.onStop() 

总结:

Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0

Activity的启动流程涉及到多个进程之间的通讯这里主要是ActivityThread与ActivityManagerService之间的通讯

ActivityThread向ActivityManagerService传递进程间消息通过ActivityManagerNative,ActivityManagerService向ActivityThread进程间传递消息通过IApplicationThread。

ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,保存请求信息等一系列操作。

ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作,并且IApplication进程间通讯告诉应用程序继承执行当前栈顶的Activity的onPause方法;

ActivityThread接收到SystemServer的消息之后会统一交个自身定义的Handler对象处理分发;

ActivityThread执行完栈顶的Activity的onPause方法之后会通过ActivityManagerNative执行进程间通讯告诉ActivityManagerService,栈顶Actiity已经执行完成onPause方法,继续执行后续操作;

ActivityManagerService会继续执行启动Activity的逻辑,这时候会判断需要启动的Activity所属的应用进程是否已经启动,若没有启动则首先会启动这个Activity的应用程序进程;

ActivityManagerService会通过socket与Zygote继承通讯,并告知Zygote进程fork出一个新的应用程序进程,然后执行ActivityThread的mani方法;

在ActivityThead.main方法中执行初始化操作,初始化主线程异步消息,然后通知ActivityManagerService执行进程初始化操作;

ActivityManagerService会在执行初始化操作的同时检测当前进程是否有需要创建的Activity对象,若有的话,则执行创建操作;

ActivityManagerService将执行创建Activity的通知告知ActivityThread,然后通过反射机制创建出Activity对象,并执行Activity的onCreate方法,onStart方法,onResume方法;

ActivityThread执行完成onResume方法之后告知ActivityManagerService onResume执行完成,开始执行栈顶Activity的onStop方法;

ActivityManagerService开始执行栈顶的onStop方法并告知ActivityThread;

ActivityThread执行真正的onStop方法;

启动流程进程间简单分析:

Zygote进程 –> SystemServer进程 –> 各种系统服务 –> 应用进程 

在Actvity启动过程中,其实是应用进程与SystemServer进程相互配合启动Activity的过程,其中应用进程主要用于执行具体的Activity的启动过程,回调生命周期方法等操作,而SystemServer进程则主要是调用其中的各种服务,将Activity保存在栈中,协调各种系统资源等操作。

通过ActivityManagerNative –> ActivityManagerService实现了应用进程与SystemServer进程的通讯 

通过AppicationThread <– IApplicationThread实现了SystemServer进程与应用进程的通讯

ActivityManagerProxy相当于Proxy

ActivityManagerNative就相当于Stub

ActivityManagerService是ActivityManagerNative的具体实现,换句话说,就是AMS才是服务端的具体实现!

ApplicationThreadProxy相当于Proxy

ApplicationThreadNative相当于Stub

ApplicationThread相当于服务器端,代码真正的实现者!

点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

system_server进程接收到请求后,向zygote进程发送创建进程的请求;

Zygote进程fork出新的子进程,即App进程;

App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

Launch Mode

先来说说在ActivityInfo.java中定义了4类Launch Mode:

LAUNCH_MULTIPLE(standard):最常见的情形,每次启动Activity都是创建新的Activity;

LAUNCH_SINGLE_TOP: 当Task顶部存在同一个Activity则不再重新创建;其余情况同上;

LAUNCH_SINGLE_TASK:当Task栈存在同一个Activity(不在task顶部),则不重新创建,而移除该Activity上面其他的Activity;其余情况同上;

LAUNCH_SINGLE_INSTANCE:每个Task只有一个Activity.

再来说说几个常见的flag含义:

FLAG_ACTIVITY_NEW_TASK:将Activity放入一个新启动的Task;

FLAG_ACTIVITY_CLEAR_TASK:启动Activity时,将目标Activity关联的Task清除,再启动新Task,将该Activity放入该Task。该flags跟FLAG_ACTIVITY_NEW_TASK配合使用。

FLAG_ACTIVITY_CLEAR_TOP:启动非栈顶Activity时,先清除该Activity之上的Activity。例如Task已有A、B、C3个Activity,启动A,则清除B,C。类似于SingleTop。

最后再说说:设置FLAG_ACTIVITY_NEW_TASK的几个情况:

调用者并不是Activity context;

调用者activity带有single instance;

目标activity带有single instance或者single task;

调用者处于finishing状态;

1、新的Activity类是通过类加载器方式即通过反射的方式生成的,我们可以看一下mInstrumentation.newActivity()方法:

public Activity newActivity(ClassLoader cl, String className, Intent intent)

            throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    return (Activity)cl.loadClass(className).newInstance();

}

最后调用mInstrumentation.callActivityOnCreate()

2、在mInstrumentation.callActivityOnStart(this)方法里面就会显式调用Activtiy的onStart()方法!

到这里我们也可以基本解决第二个问题:Activity的生命周期方法是通过Instrumentation类调用callActivityOnXXX方法最终调用Activity的onCreate等方法,调用时机为ActivityThread#performLaunchActivitiy()方法中。

3、ActivityThread#performResumeActivity()

  --> Activity#performResume()

    --> Instrumentation#callActivityOnResume()

      --> Activity#onResume()

另外,观察执行handleResumeActivity()之后的代码,会发现程序会开始获取DecorView,执行addView()方法,里面最终会调用到ViewRootImpl#performTraversals(),即开始绘制view界面!

这里我们就解决了第三个问题:界面的绘制是在执行Activity#onResume()之后!

4、ActivityThread的main方法是在生成一个新的app进程过程中调用的,具体是通过与Zygote通信,之后通过RuntimeInit类采用反射的方式调用ActivityThread#main()方法,即生成app中的主线程(UI线程)!

可以关注我的公众号:Android架构师成长之路

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343