Android 四大组件中的两个的工作流程(Activity和Service)

  • Post author:
  • Post category:其他


一,Activity的启动过程

Activity 的启动过程分为两种, 一种是根 Activity 的启动过程,另 一种是普通 Activity的启动过程。根 Activity 指的是应用程序启动的第一个 Activ町,因此根 Activity 的启动过程一般情况下也可以理解为应用程序的启动过程。普通 Activ即指的是除应用程序启动的

第一个 Activity 之外的其他 Activity 。这里介绍的是根 Activity 的 启动过程 ,它和普通 Activity的启动过程是有重 叠部分的,只不过根 Activity 的启动过程一般情况下指的就是应用程序的启动过程,更具有指导性意义。

根 Activity 的启动过程比较复杂,因此这里分为 3 个部分来讲,分别是 Launcher 请求AMS 过程、 AMS 到 Application Thread 的调用过程和 ActivityThread 启动 Activity 。

1,Launcher 请求 AMS 过程

Launcher 启动后会将已安装应用程序的快捷图标显示到桌面上,这些应用程序的快捷图标就是启动根 Activity 的入口,当我们点击某个应用程序的快捷图标时,就会通过 Launcher 请求 AMS 来启动该应用程序 。

首先,当我们点 击应用程序 的快捷图标时,就会调用 Launcher 的 startActivitySafely 方法

packages/apps/Launcher3/src/co m/android/launcher3/Launcher.j ava中的源码

intent.addFlags(Intent .FLAG_ACTIVITY_NEW_TASK)//表示根Activity会在新的任务栈中启动

startActivity(intent , optsBundle) ;//此方法在Activity中实现

自 Override
public void startAct 工V工 ty(Intent intent , @Nullable Bundle options)
if (opt i ons 1= null) {
startActivityForResult(inte nt , - 1 , options) ;
} else {
startActivityForResult(inte nt , - 1) ;
}
}

在 startActivity 方战中 会调用 startActivity F orResult 方怯,它的第二个参数为- 1 , 表示Launcher 不需要知道 Activity 启 动的结果 , startActivityForResult 方怯的代码如下所示:

public void startActivityForResult (@RequiresPerm工 ssion Intent inte口 t , int
@Nullable Bundle options) {
if (mParent = null) {/ /1
options = transferSpringboardAct 工V 工 tyOptio 口 s(opt 工 ons) ;
Instrumentation . ActivityResult ar =
reqi且estCode ,
minstrumentation . execStartAct 工vity (
this , mMainThread . getApplicationThread (),
intent , requestCode , optio 口 s );
mToke 口 ,
this ,
} el se {
。。。。。
}
}

此处需要注意的是Instrumenttation中的execStartActivity()方法,他主要是用来监控应用程序和系统的交互的

在这个方法中,首先调用ActivityManager 的getServer方法来获取AMS的代理对象,接着调用他的startActivity方法

getService 方告调用了 IActivityManagerSingleton 的 get 方?去,我们接 着 往下看,IActivityManagerSingleton 是一个 Singleton 类。 在注释 l 处得到 名 为“ activity ”的 Service引用 , 也就是 !Binder 类型的 AMS 的引用 。 接着在注释 2 处将它转换成!Activity Manager类型的对象,这段代码采用的是 AIDL, IActivityManager.java 类是由 AIDL 工具在编译时自动 生 成的,IActivityManager.aidl 的文件路 径 为 frameworks/base/core/java/android/app/IActivityManager.aidl 。要 实 现进程|可通信,服务 器 端也就是 AMS 只需要继承IActi vity Manager. S阳b 类 并实现相 应 的 方也就可以了。 注意 Android 8.0 之前并没有采用AIDL ,而是采用了类似 AIDL 的形式,用 AMS 的代理对象 Activity Manager Proxy 来与 AMS进行进程间通信, Android 8.0 去除了 ActivityManager忖ative 的内部类 ActivityManagerProxy,代 替 它的是!ActivityManager ,它是 AMS 在本 地的代理 。回 到 Instrumentation 类的execStartActivity 方法中,

从上 面得 知 execStartActi vi ty 方法最 终调用的是 AMS 的startActivity 方怯 。

2,AMS 到 Application Thread 的调用过程

AMS 的 startActivity 方怯如下所示


public final int startActivity(IApplicationThread caller, String callingPackage ,
Intent intent , String resolvedType , IBinde r resultTo , String resultWho ,
int requestCode , int startFlags , Profilerlnfo profilerlnfo , Bundle
bOptions ) {
return startActivityAsUser (caller , callingPackage , intent , resolvedType ,
resultTo , resultWho , requestCode , startFlags , prof 工 lerlnfo , bOptions ,
Us erHandl e . getCallingUserid ());

在 AMS 的 startActivity 方法中返回了 startActivityAsUser 方法 , 可以发现 startActivity As User方怯 比 startActivity 方居 多 了 一个参数 UserHandle.getCallingUserld(), 这个方 怯会获得调用者的 Userld, AMS 根据这个 UserId 来确定调用 者 的权限。

//判断调用者进程是否被隔离

enforceNotis 。latedCaller (” startActivity ”)

//检查调用者权限

user Id= mUserController.handleincomingUser(Binder.getCallingPid(), Binder.

getCallingUid(), userid, false ,ALLOW_FULL_ONLY ,” startActivity ”, null) ;

在此源码中显示,调用了 ActivityStarter 的 startActiviηLocked 方怯, startActivityLocked 方陆的 参数 要比startActi vi ty As User 多 几个 ,需要注意 的是倒数第二个参数类型 为 TaskRecord ,代表启动的Activ ity 所在的栈。最后一个参数” startActivityAsUser” 代表启动的理由。 ActivityStarter 是 Android 7.0 中新加入的类,它是加载 Activity 的控制类 , 会收集所有的逻辅来决定如何将 Intent 和 Flags 转换为 Activity ,并将 Activity 和 Task 以及 Stack 相 关

联。 ActivityStarter 的 startActivityMayWait 方法i周用了 startActivityLocked 方法

在此方法中,继续调用startActivityUnchecked方法,此方法,主要处理与枝管理相关的逻辑 。在标注1处我们得知,启动根 Activity 时会将 Intent 的 Flag 设置为 FLAG ACTIVITY NEW TASK ,这样注释 l处的条件判断就会楠a 足 , 接 着执行注释 2 处的 setTaskFromReuseOrCreateNewTask 方怯,其内部会创建 一 个新的 TaskRecord ,用来描述 一 个 Activity 任务枝,也就是说setTaskFromReuseOrCreateNewTask 方怯内部会创建一个新的 Activ句任务挠。 Activity 任

务钱其实是一个假想的模型,并不真实存在

最终,代码执行到ActivityThread中去执行了,不知道你们晕没晕,反正我是比较晕的,

总之一句话,就是,Activity启动的传递时间,是一层一层的传递到了ActivityThread里面了

Activity Thread 启动 Activity 的过程

终于走到这里了,这里我也不想写了,我就解释一下上图中的某些函数的意义吧

ApplicationThread 的 scheduleLaunchActivity 方法,将启动 Activity 的参数封装成 ActivityClientRecord,sendMessage 方怯向 H 类发送类型为 LAUNCH一ACTIVITY 的消息,并将 Activ町ClientRecord传递过去, sendMessage 方陆有 多个重载方法。H ,它是 ActivityThread 的内部类并继承 自 Handler ,是应用程序进程中 主 线程的消息管理类。 因为 ApplicationThread 是一个 Binder ,它的调用逻辑运行在 Binder线程池中,所以这里需要用 H 将代码的逻辑切换到 主 线程中,然后通过Instrumentation中的performCreate方法传递到Activity中去执行操作

根 Activity 启动过程中涉及的进程

根 Activity 启动过程中 会涉及 4 个进程,分别是 Zygote 进程 、 Launcher 进程、 AMS 所在进程( SystemServer 进程)、应用程序进程。关系图如下

首先 Launcher 进程向 AMS 请求创建根 Activity,AMS 会判断根 Activity 所需的应用程序进程是否存在井启动,如果不存在就会请求 Zygote进程创建应用程序进程 。 应用程序进程启动后, AMS 会请求创建应用程序进程并启动根Activity 。

二,Service 的启动过程

Contextlmpl 到 AMS 的调用过程

手绘一张时序图奉上:


ActivityThread启动Service



版权声明:本文为u011228868原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。