本文以图文形式简单介绍了一个APP从启动到主页面显示的过程,以及实现原理。具体的源码就不介绍了,只搭建了一个大概的框架。流程概述启动流程:①点击桌面App图标,Launcher进程使用BinderIPC向system_server进程发起startActivity请求;②system_server进程收到请求后,向zygote进程发送创建进程的请求;③Zygote进程fork出一个新的子进程,即App进程;④App进程,通过BinderIPC向sytem_server进程发起attachApplication请求;⑤system_server进程收到请求后,进行一系列准备工作,然后通过binderIPC向App进程发送scheduleLaunchActivity请求;⑥App进程的binder线程(ApplicationThread)收到请求后通过handler向主线程发送LAUNCH_ACTIVITY消息;⑦主线程收到Message后通过launch机制创建目标Activity,并回调Activity.onCreate()等方法。⑧至此,App正式启动,进入Activity生命周期。执行onCreate/onStart/onResume方法后,即可看到UI渲染完成后的App主界面。以上一系列步骤简单介绍了一个APP开始展示到主页面的过程。也许这些过程中的某些术语有点令人困惑。什么是Launcher,什么是zygote,什么是applicationThread.....下面我们一一介绍。二、理论依据1.zygotezygote意为“受精卵”。Android是基于Linux系统的,在Linux中,所有进程都是由init进程直接或间接fork出来的,zygote进程也不例外。在Android系统中,zygote是一个进程的名称。Android基于Linux系统。当你的手机开机时,Linux内核加载完成后,会启动一个名为“init”的进程。在Linux系统中,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。我们都知道每个App其实就是一个独立的dalvik虚拟机,一个独立的进程,所以当系统中第一个zygote进程运行时,启动之后的App就相当于启动了一个新的进程。Android系统为了实现资源共享和更快的启动速度,通过fork第一个zygote进程来启动一个新的进程。所以,除了第一个zygote进程外,其他应用程序的进程都是zygote的子进程。现在你明白为什么这个过程被称为“受精卵”了吧?因为它就像一个受精卵,可以很快2.system_serverSystemServer也是一个进程,它是由zygote进程fork出来的。了解了SystemServer的本质,我们就不会太陌生了。这个进程是AndroidFramework中两个非常重要的进程之一——另一个进程就是上面的zygote进程。为什么SystemServer很重要?因为系统中重要的服务都是在这个过程中启动的,比如ActivityManagerService、PackageManagerService、WindowManagerService等。3.ActivityManagerServiceActivityManagerService,简称AMS,是一个服务器对象,负责系统中所有活动的生命周期。ActivityManagerService初始化的时机很明确,就是在SystemServer进程启动的时候,ActivityManagerService就会被初始化。下面介绍一下Android系统中server和client的概念。事实上,服务器客户端的概念不仅存在于Web开发中,在Android的框架设计中也使用了这种模式。服务器端指的是所有App共享的系统服务,比如我们这里提到的ActivityManagerService,还有上面提到的PackageManagerService、WindowManagerService等。这些基础系统服务是所有App共享的。当一个App要执行某个操作时,需要告诉这些系统服务。比如你要打开一个App,那么我们知道包名和MainActivity类名就可以打开了。意图intent=newIntent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_LAUNCHER);ComponentNamecn=newComponentName(packageName,className);intent.setComponent(cn);startActivity(intent);但是,我们的App不能通过调用startActivity()直接打开另一个App,这个方法会经过一系列的调用,***还是告诉AMS:“我要打开这个App,我知道它的地址和名称,请为我!”所以是AMS通知zygote进程fork一个新的进程来打开我们的目标App。就像浏览器想要打开超链接一样。浏览器将网页地址发送给服务器,然后服务器将需要的资源文件发送给客户端。了解了AndroidFramework的client-server架构之后,我们还需要了解一件事,那就是我们的App、AMS(SystemServer进程)和zygote进程属于三个独立的进程。他们如何沟通?App通过Binder与AMS进行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一样,它也继承自Activitypackages/apps/Launcher2/src/com/android/launcher2/Launcher.javapublicfinalclassLauncherextendsActivityimplementsView.OnClickListener,OnLongClickListener,LauncherModel.Callbacks,View.OnTouchListener{}Launcher实现了点击、长按等回调接口接收用户输入。由于是一个普通的app,我们的开发经验在这里还是适用的。例如,当我们点击图标时,我们如何启动应用程序?捕获图标点击事件,然后startActivity()发送相应的Intent请求!是的,Launcher也有同样的功能,就是这么简单!5.Instrumentation和ActivityThread每个Activity都持有一个Instrumentation对象的引用,但是整个进程中只会有一个Instrumentation对象。Instrumentation类中的大部分方法都与Application和Activity相关。该类是一个工具类,完成Application和Activity的初始化和生命周期。Instrumentation类很重要,Activity生命周期方法的调用离不开他。他可以说是一个大管家。ActivityThread是UI线程。App与AMS通过Binder传递信息,所以ActivityThread专门与AMS进行外交工作。6.ApplicationThread我们已经知道App的启动和Activity的显示都需要AMS控制,所以我们需要和服务端进行通信,而这种通信是双向的。Client->Server并且由于继承了相同的公共接口类,ActivityManagerProxy提供了与ActivityManagerService相同的函数原型,让用户感觉不到Server是运行在本地还是远程,从而可以更方便的系统调用这些重要的功能服务。server-->client仍然通过Binder进行通信,但是换成了另一对,ApplicationThread和ApplicationThreadProxy。也都实现了相同的接口IApplicationThreadprivateclassApplicationThreadextendsApplicationThreadNative{}publicabstractclassApplicationThreadNativeextendsBinderimplementsIApplicationThread{}classApplicationThreadProxyimplementsIApplicationThread{}嗯,前面啰嗦了一大堆,介绍了一堆名词。可能不太清楚,没关系,我们用流程图来介绍一下。三、启动流程1、创建流程①首先,通过Binder通信从Launcher的startActivity()方法中调用ActivityManagerService的startActivity方法。②一系列的折腾,最后调用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()方法。将进程绑定到指定的应用程序。这是通过调用上一节中ActivityThread对象中的bindApplication()方法来完成的。该方法向消息队列发送BIND_APPLICATION消息,最后通过handleBindApplication()方法处理消息。然后调用makeApplication()方法将App类加载到内存中。方法调用流程图如下:更直白的流程解释:(AMS、ATP等名词如果不懂,后面会有解释)3.显示Activity界面经过前两步,系统已经有了应用程序的进程。后续调用序列是从现有流程启动新流程的正常活动。实际的调用方法是realStartActivity(),会调用应用线程对象中的scheduleLaunchActivity()向消息队列发送LAUNCH_ACTIVITY消息,通过handleLaunchActivity()处理消息。在handleLaunchActivity()中,通过performLaunchActivity()方法回调Activity的onCreate()和onStart()方法,然后通过handleResumeActivity()方法回调Activity的onResume()方法,最后显示活动界面。更直白的流程解释:4、Binder通信简称:ATP:ApplicationThreadProxyAT:ApplicationThreadAMP:ActivityManagerProxyAMS:ActivityManagerService示意图:①在system_server进程中调用startProcessLocked方法,最终通过socket方法通知Zygote进程需要创建新进程,并阻塞并等待Socket返回新创建进程的pid;②Zygote进程接收到system_server发来的消息,然后使用fork方法复制zygote自身进程生成新进程,并将ActivityThread相关资源加载到新进程app进程中,这个进程可能用来承载活动等组成部分;③在新建进程app进程中,查询system_server进程中binderserverAMS的servicemanager,获取对应的client,即AMP。有了这对binderc/s,那么app进程就可以通过binder向跨进程的system_server发送请求,即attachApplication()④system_server进程收到对应的binder操作后,使用ATP发送一个binder多次调用后向app进程请求,即bindApplication.system_server有ATP/AMS,每一个新创建的进程都会有一个对应的AT/AMP,这样就可以跨进程通信了。这就是流程创建过程的完整生态链。以上大致介绍了一个APP从启动到显示主页面的过程。主要是从宏观的角度介绍流程,结合源码可以理解。
