写点什么

论一个 APP 从启动到主页面显示经历的过程?

用户头像
Android架构
关注
发布于: 8 小时前
3.ActivityManagerService

ActivityManagerService,简称 AMS,服务端对象,负责系统中所有 Activity 的生命 周期。 ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启 的时候,就会初始化ActivityManagerService


下面介绍下 Android 系统里面的服务器和客户端的概 念。


其实服务器客户端的概念不仅仅存在于 Web 开发中,在 Android 的框架设计中,使 用的也是这一种模式。服务器端指的就是所有 App 共用的系统服务,比如我们这里 提到的ActivityManagerService,和前面提到的PackageManagerServiceWindowManagerService等等,这些基础的系统服务是被所有的 App 公用的,当某 个 App 想实现某个操作的时候,要告诉这些系统服务,比如你想打开一个 App,那 么我们知道了包名和MainActivity类名之后就可以打开


Intent intent = new Intent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_LAUNCHER);ComponentName cn = newComponentName(packageName, className);intent.setComponent(cn); startActivity(intent);


但是,我们的 App 通过调用startActivity()并不能直接打开另外一个 App,这个方法会 通过一系列的调用,最后还是告诉 AMS 说:“我要打开这个 App,我知道他的住址和 名字,你帮我打开吧!”所以是 AMS 来通知 zygote 进程来 fork 一个新进程,来开启我 们的目标 App 的。这就像是浏览器想要打开一个超链接一样,浏览器把网页地址发 送给服


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


务器,然后还是服务器把需要的资源文件发送给客户端的。


知道了 Android Framework 的客户端服务器架构之后,我们还需要了解一件事情, 那就是我们的 App 和AMS(SystemServer进程)还有 zygote 进程分属于三个独立的进 程,他们之间如何通信呢?


App 与AMS通过 Binder 进行IPC通信,AMS(SystemServer进程)与 zygote 通过 Socket 进行IPC通信。后面具体介绍。


那么AMS有什么用呢?在前面我们知道了,如果想打开一个 App 的话,需要AMS去 通知 zygote 进程,除此之外,其实所有的 Activity 的开启、暂停、关闭都需要AMS 来控制,所以我们说,AMS负责系统中所有 Activity 的生命周期。 在 Android 系统中,任何一个 Activity 的启动都是由AMS和应用程序进程(主要是 ActivityThread)相互配合来完成的。AMS服务统一调度系统中所有进程的 Activity 启动,而每个 Activity 的启动过程则由其所属的进程具体来完成。

4.Launcher

当我们点击手机桌面上的图标的时候,App 就由 Launcher 开始启动了。但是,你有 没有思考过 Launcher 到底是一个什么东西? Launcher 本质上也是一个应用程序,和我们的 App 一样,也是继承自Activity packages/apps/Launcher2/src/com/android/launcher2/Launcher.java


public final class Launcher extends Activityimplements View.OnClickListener, OnLongClickListener, La uncherModel.Callbacks, View.OnTouchListener {}


Launcher 实现了点击、长按等回调接口,来接收用户的输入。既然是普通的 App, 那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启 的应用呢?捕捉图标点击事件,然后startActivity()发送对应的 Intent 请求呗!是的,Launcher 也是这么做的,就是这么 easy!

5.Instrumentation 和 ActivityThread

每个 Activity 都持有Instrumentation对象的一个引用,但是整个进程只会存在一个 Instrumentation对象。 Instrumentation这个类里面的方法大多数和ApplicationActivity有关,这个类就是完成对ApplicationActivity初始化和生命周期的工具 类。Instrumentation这个类很重要,对 Activity 生命周期方法的调用根本就离不开 他,他可以说是一个大管家。


ActivityThread,依赖于 UI 线程。App 和AMS是通过 Binder 传递信息的,那么 ActivityThread就是专门与AMS的外交工作的。

6.ApplicationThread

前面我们已经知道了 App 的启动以及 Activity 的显示都需要AMS的控制,那么我们便 需要和服务端的沟通,而这个沟通是双向的。客户端-->服务端



而且由于继承了同样的公共接口类,ActivityManagerProxy提供了与 ActivityManagerService一样的函数原型,使用户感觉不出 Server 是运行在本地还是 远端,从而可以更加方便的调用这些重要的系统服务。


服务端-->客户端还是通过 Binder 通信,不过是换了另外一对,换成了ApplicationThreadApplicationThreadProxy



他们也都实现了相同的接口IApplicationThread


private class ApplicationThread extends ApplicationThreadNative {}public abstract class ApplicationThreadNative extends Binder i mplements IApplicationThread{}class ApplicationThreadProxy implements IApplicationThread {}


好了,前面罗里吧嗦的一大堆,介绍了一堆名词,可能不太清楚,没关系,下面结 合流程图介绍。

三、启动流程

1.创建进程

先从 Launcher 的startActivity()方法,通过 Binder 通信,调用 ActivityManagerServicestartActivity方法。 一系列折腾,最后调用startProcessLocked()方法来创建新的进程。 该方法会通过前面讲到的 socket 通道传递参数给 Zygote 进程。Zygote 孵化自身。 调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的 pid。 调用ActivityThread.main()方法,ActivityThread随后依次调用 Looper.prepareLoop()Looper.loop()来开启消息循环。


方法调用流程图如下:



更直白的流程解释:



①App 发起进程:当从桌面启动应用,则发起进程便是 Launcher 所在进程;当从某 App 内启动远程进程,则发送进程便是该 App 所在进程。发起进程先通过 binder 发送 消息给system_server进程;②system_server 进程:调用Process.start()方法,通过 socket 向 zygote 进程发送创 建新进程的请求;③zygote 进程:在执行ZygoteInit.main()后便进入runSelectLoop()循环体内,当有 客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后 fork 出新的应用进程;④新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法。

2.绑定 Application

上面创建进程后,执行ActivityThread.main()方法,随后调用 attach()方法。


将进程和指定的Application绑定起来。这个是通过上节的ActivityThread对象中调用 bindApplication()方法完成的。该方法发送一个BIND_APPLICATION的消息到消息 队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用 makeApplication()方法来加载 App 的 classes 到内存中。


方法调用流程图如下:



更直白的流程解释:



(如果看不懂 AMS,ATP 等名词,后面有解释)

3.显示 Activity 界面

经过前两个步骤之后, 系统已经拥有了该application的进程。 后面的调用顺序就是 普通的从一个已经存在的进程中启动一个新进程的 activity 了。


实际调用方法是realStartActivity(), 它会调用 application 线程对象中的 scheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息。在 handleLaunchActivity()通过 performLaunchActiivty()方法回调 Activity 的onCreate()方法和onStart()方法,然后通 过handleResumeActivity()方法,回调 Activity 的onResume()方法,最终显示 Activity 界面。



更直白的流程解释:


四、Binder 通信


简称:ATP: ApplicationThreadProxy AT: ApplicationThread AMP: ActivityManagerProxyAMS: ActivityManagerService


图解:


system_server 进程中调用startProcessLocked方法,该方法最终通过 socket 方式, 将需要创建新进程的消息告知 Zygote 进程,并阻塞等待 Socket 返回新创建进程的 pid; Zygote 进程接收到 system_server 发送过来的消息, 则通过 fork 的方法,将 zygote 自身进程复制生成新的进程,并将ActivityThread相关的资源加载到新进程 app process,这个进程可能是用于承载 activity 等组件; 在新进程 app process 向servicemanager查询 system_server 进程中 binder 服务端 AMS, 获取相对应的 Client 端,也就是 AMP. 有了这一对 binder c/s 对, 那么 app process 便可以通过 binder 向跨进程 system_server 发送请求,即attachApplication() system_server进程接收到相应 binder 操作后,经过多次调用,利用 ATP 向app process发送 binder 请求, 即bindApplication. system_server拥有 ATP/AMS, 每一个 新创建的进程都会有一个相应的 AT/AMP,从而可以跨进程 进行相互通信. 这便是进 程创建过程的完整生态链。


以上大概介绍了一个 APP 从启动到主页面显示经历的流程,主要从宏观角度介绍了 其过程,具体可结合源码理解。


顺手留下 GitHub 链接,需要获取相关面试等内容的可以自己去找https://github.com/xiangjiana/Android-MS(VX:mm14525201314)

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
论一个APP从启动到主页面显示经历的过程?