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


                                                   浅析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;">ActivityThread
    ApplicationThread
    ActivityManagerService
    
    Instrumentation
    
    ActivityRecord
    ProcessRecord
    TaskRecord
    ActivityStack
    
    ActivityManagerProxy
    ApplocationThreadProxy</span>

    参考文献:

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


  • 相关阅读:
    实际项目管理-1
    arcengine 错误
    一些视频技术类网站
    winform 组件之dotnetbar10.5.3
    winform 弹框的组件
    一个好的开源网站
    写webservice 注意点
    ww
    js
    瀑布流
  • 原文地址:https://www.cnblogs.com/Spground/p/8536162.html
Copyright © 2020-2023  润新知