浅析Android系统中的Activity启动过程

来源:互联网 发布:淘宝上几十块的人参 编辑:程序博客网 时间:2024/05/18 18:14

                                              浅析Android系统中的Activity启动过程

一、Activity的启动分为三种类型
1.根Activity的启动,通常就是程序的MainActivity的启动,这个是通过用户点击桌面程序(Launcher)的App的图标,
从而导致对应的App在一个新的进程中被启动起来
2.在同一个进程启动子Activity
3.在新的进程启动子Activity

对应第一种类型来讲,主要是有如下分析:
首先根ACtivity的启动涉及到三个不同的进程,依次是Launcher所在进程,MainActivity所在进程,ActivityManagerService所在进程。
其中ActivityManagerService是系统关键服务,他是用来管理系统Activity组件的一个服务,优先级特别高。任何app的Activity的活动都需要与它交互。既然涉及到这么多个进程的交互,那么必然涉及到Android系统中的Binder进程通讯。

其次就是Launcher启动MainActivity的过程分析,大致分为6个阶段


p1:当用户点击桌面app的图标时,Launcher(其实就是一个Activity。或者叫做继承自Activity)就获取到App的一些信息(比如,包名,路径等)(这些信息其实是Launcher通过查询PackageManagerService获得的),Launcher拿着这些信息然后去向ActivityManagerService请求一次进程间通信,表示我想要启动某个App的MainActivity。

p1.1

p1.2


p2.ActivityManagerService收到进程间请求后,会做两件事情,第一将刚刚收到的关于启动MainActivity的信息保存下来(这些信息包括ActivityRecord等), 第二向Launcher发送一次进程间通信请求,请求Launcher进入Pause状态,这样有利于Launcher在MainActivity启动起来时,自己可以做一些操作,例如保存状态信息,以便于Launcher后面Resume。

p2

p3.Launcher收到了ActivityManagerService的进程间通信请求后,就会进入到Paused状态,进入到状态后,会立马向ActivityManagerService再次发送一次进程间通信请求,表示我已经进入了Paused状态,你可以放心的去启动MainActivity了。值得注意的是,ActivityManagerSerice有一个超时机制,如果Launcher在指定的时间没有进入Paused状态,即ActivityManagerService没有及时收到Launcher组件的再一次进程间通信请求,ActivityManagerService会认为Launcher无响应。



p3

p4.ActivityManagerService收到了Launcher再次发来的进程间通信请求后,它知道是时候为启动MainActivity干点正事了,它根据启动MainActivity的信息发现了MainActivity所在的运行进程并不存在,因此就会新启动一个新的进程来运行MainActivity,新的进程程序入口是ActivityThread的public final static void main(String[] args)

p4

p5.新的进程启动完成以后,(进程的程序入口 是ActivityThread的public final static void main(String[] args)),就会向ActivityManagerService发送一个进程间通信请求,表示新的进程已经准备就绪,随时可以起飞,请指示。

p5

p6.ActivityManagerService收到以后,会将p2阶段保存下来的关于MainActivity的信息做一次进程间通信请求,将信息发送给新进程,让新进程运行MainActivity。

p6

自此一个新的App进程被创建,MainActivity被启动起来,运行在这个新的进程中。

这里一个6个阶段,共涉及到5次进程间通信,其中Launcher与ActivityManagerService之间进行了3次,ActivityManagerService与MainActivity所在进程之间进行了2次。
其中涉及到的进程间通信请求具体如下:
-----------------------------------------------------------------------------------------------------------------------
id     phase                            detail
-----------------------------------------------------------------------------------------------------------------------
#1      p1:      Launcher所在进程 ----START_ACTIVITY_TRANSACTION----> ActivityManagerService所在进程

#2   p2:     ActivityManagerService所在进程 ----SCHEDULE_PAUSE_ACTIVITY_TRANSACTION----> Launcher所在进程

#3   p3:    Launcher所在进程 ----ACTIVITY_PAUSED_TRANSACTION----> ActivityManagerService所在进程

#4   p5:    MainActivity(新建进程) ----ATTACH_APPLICATION_TRANSACTION----> ActivityManagerService

#5   p6:     ActivityManagerService所在进程 ----SCHEDULE_LANUCHER_ACTIVITY_TRANSACTION----> MainActivity(新建进程)
-----------------------------------------------------------------------------------------------------------------------



二、对应第二种类型分析如下:
由于在同一个进程中,一个Activity启动另一个Activity,这两个Activity都是运行在同一个进程中的,因此相比于前面分析的第一种类型,就少了ActivityManagerService去新建一个进程和新建进程对ActivityManagerService做一次ATTACH_APPLICATION_TRANSACTION请求这个步骤
值得注意的是,由于MainActivity去启动一个子Activity是在同一个App中进行的并且没有特别指明taskAffinity,因此他们启动后再ActivityManagerService中都是同属于一个Task的,而非不同的Task。

三、对应于第三种类型分析如下:
由于是在同一个App中,但是两个Activity试运行在不同的进程中的,因此相比于第一种类型,有一点相似之处,但是不同的是两个Activity所属于的Task是一样的,因为他们虽然不属于同一个进程,但是他们是属于一个app的,是属于密切联系的一个用户任务,因此理所当然的就应该是在同一task中了。

每一个Activity都是运行在一个Task中的,Task是一个比进程更加高级和抽象的概念,由于Android的App可以拥有多个不同的进程,用Task去描述一系列相关的功能比用进程去描述更加容易理解和描述。一个Task可以包含运行在不同进程中的Activity,因此可以很好的提高Activity的可重用性。(比如你的App想要查看一张照片,那么任何App提供查看照片能力的Activity都可以添加到你的App所在的Task中,虽然他们是运行在不同进程,而且甚至是不同uid中的,但是由于Task的存在,用户丝毫感觉不到是两个App, 这样查看照片的Activity就可以得到复用)

四、总结
这个过程涉及到几个主要的类:
<span style="font-size:18px;">ActivityThreadApplicationThreadActivityManagerServiceInstrumentationActivityRecordProcessRecordTaskRecordActivityStackActivityManagerProxyApplocationThreadProxy</span>

参考文献:

[1]罗升阳.Android系统源代码情景分析[M].北京:电子工业出版社,2012:393-443


1 0
原创粉丝点击