在安卓系统中,从点击应用图标到应用显示的过程可以大致分为以下几个阶段,下面我将详细解释并参考相关信息来阐述这一过程:
1.启动阶段:
当用户在桌面上点击一个应用图标时,会触发Launcher进程(桌面进程)的动作。
Launcher进程通过Binder机制向Activity Manager Service(AMS)发送一个startActivity请求。
AMS收到请求后,会检查需要启动的Activity所属的进程是否已存在。如果不存在,则通过socket IPC向Zygote进程发送请求,以创建新的应用进程。
2.进程创建:
Zygote进程接收到来自AMS的请求后,会fork出一个新的应用进程。新进程会加载ActivityThread类,并调用其main()方法,这是应用进程的入口点。
3.应用进程初始化:
在main()方法中,会进行一系列初始化操作,包括初始化并开启主线程Looper消息循环、初始化Application对象等。应用进程与AMS建立Binder通信,确保后续能够接收AMS发送的各种事件和指令。
4.Activity启动:
AMS将新启动的Activity以ActivityRecord的结构压入Activity栈中。如果当前有正在运行的Activity(即前一个Activity),则通过Binder回调通知其进入pause状态。AMS通过远程调用告知新进程启动Activity,并加载相应的界面。
5.Activity界面加载:
在新进程中,会通过反射调用Application的onCreate方法和Activity的onCreate方法。
Activity会执行其生命周期中的onCreate、onStart、onResume等方法,准备并显示界面。
6.界面绘制与显示:
Activity在onResume之后,会进行界面的绘制工作。这包括Measure(测量)、Layout(布局)和Draw(绘制)三个核心步骤。应用层将绘制好的surface缓存数据通过SurfaceFlinger服务渲染到屏幕上。最终,用户看到的就是已经启动并显示出来的应用界面。
总结来说,从点击应用图标到应用显示的过程涉及了多个组件之间的交互和协作,包括Launcher进程、AMS、Zygote进程、应用进程以及Activity等。这个过程既包含了进程的创建和初始化,也包含了Activity的启动和界面的绘制与显示。
整个过程涉及到几个进程?
整个过程大概涉及四个进程(严格来说有5个,即还有一个ServiceManager),分别是Laucher进程(桌面APP),SystemServer进程(AMS所属进程),Zygote进程(系统和所有APP的创建进程),APP进程。
为什么AMS(Activity Manager Service)通过socket与Zygote通信,而不是使用Binder机制?
1.启动顺序和注册时机:
在Android系统启动过程中,Binder驱动是早于init进程加载的。init进程是安卓系统启动的第一个进程,它会创建ServiceManager进程和Zygote进程。由于ServiceManager和Zygote的创建是并行的,虽然ServiceManager通常会更早创建,但并不能保证在Zygote进程尝试注册Binder服务时,ServiceManager已经完全初始化好。
如果AMS想要通过Binder向Zygote发送请求,它必须首先从ServiceManager中获取Zygote的Binder引用,但这是在Zygote进程成功注册其Binder服务之后才能发生的。由于启动顺序和注册时机的不确定性,使用Binder进行通信可能会导致问题。
2.多线程和死锁风险:
Binder通信是需要多线程操作的。在Android中,AMS与应用进程通信时,AMS的本地代理IApplicationThread通过Binder线程调用应用进程的ApplicationThread。如果AMS尝试通过Binder向Zygote发送信号,并且Zygote的父进程(如SystemServer)的Binder线程有锁,那么可能会导致死锁,因为子进程(从Zygote fork出来的)的主线程可能正在等待其子线程(从父进程拷贝过来的)的资源,但实际上这些资源并没有被拷贝过来。
3.通信效率和简洁性:
Socket通信在这种情况下可能更加简单和高效。由于Zygote主要负责创建新的应用进程,AMS和Zygote之间的通信相对简单且直接,使用socket可以更快地完成进程创建和状态传递。
综上所述,AMS通过socket与Zygote通信主要是为了避免由于启动顺序和注册时机导致的问题,以及减少多线程操作可能带来的死锁风险。同时,这种通信方式也更加简单和高效,适用于AMS和Zygote之间相对简单且直接的通信需求。