Android的Activity启动流程
一个Android系统的手机,面对桌面一大堆的应用图标,我们随便点击一个应用图标,打开该应用,然后就进行了该系统的业务流程,登录注册等等之类。那我们开发者在最初写项目的时候,都知道要有一个入口Activity,并且需要在AndroidManifest.xml配置action和category,这样我们点击应用图标就会首先进入这个Activity里面,这样的Activity被称作主Activity,至于都已经到了主Activity里面去了,那么如果想要跳转到其它的页面,也很简单,使用startActivity方法就可以。
那我们有没有想过,点击桌面的应用图标,为什么就可以打开这个应用了呢?Android这个系统在后面都有哪些操作呢?
Android系统是基于Linux系统的,init进程是Linux操作系统里面由内核启动的用户级线程,是系统必不可少的程序之一。Zygote进程是整个系统创建新进程的核心进程,是由init进程fork出来的。那么除了Zygote整个整个系统的根进程,还有个SystemService进程,这个进程主要作用是启动各种系统服务。比如ActivityManagerService、PackageManagerService、WindowManagerService等等。
那么我们平时Android手机看到的桌面其实也是一个应用程序,将它称作Launcher,Launcher是由系统服务LauncherAppService进行启动的,LauncherAppService则是由SystemService来启动的。
ActivityManagerService里面的systemReady方法首先,在ActivityManagerService里面可以找到systemReady方法,这个方法什么时候调用呢?又是由谁调用呢?在SystemService进程启动过程中,在其中通过内部方法分别调用了boot service,core service和other service,在调用startOtherService的时候就会调用ActivityManagerService的systemReady方法。
ActivityManagerService的systemReady方法很长,我们着重看一个
systemReady方法里面的调用startHomeActivityLocked startHomeActivityLocked的实现这个顾名思义,就是启动一个home的Activity,那么针对Android操作系统来说,桌面看作一个Activity的话, 那么毋庸置疑这个home的Activity指的就是桌面。
看看getHomeIntent方法
getHomeIntent方法有没有发现这段代码我们很熟悉,就是我们经常写的要启动一个Activity,创建出一个intent,并给intent设置Component、flag和Category,注意这里的Category是android.intent.category.HOME
那么这种启动Activity的方式很明显是属于隐士启动,查看Launcher源码得知,在AndroidManifest里面配置Category为android.intent.category.HOME的是LauncherActivity。
LauncherActivity是继承ListActivity的,看看它的布局
LauncherActivity的布局文件是不是很简单?就是一个ListView再加上个TextView,那么LauncherActivity的onCreate方法是什么样的呢?
LauncherActivity的onCreate方法我们可以发现,getPackageManager这个方法一开始就初始化了PackageManager,这个用于查询手机里面所有的应用程序包名、应用名、图标等,将这些作为数据源,放入到Adapter中,这样我们在桌面上所看到的应用程序名字和图标信息皆是来源于此。
ListView的item点击监听
ListView的onListItemClick方法很简单,就是创建一个intent,然后startActivity方式启动这个Activity。
看看intentForPosition方法
intentForPosition方法到现在为止的分析来看,Launcher程序本身就是一个安卓应用程序,只不过是系统默认启动的第一个应用程序。那我们在Launcher程序LauncherActivity提供了一个应用程序视图,可以供用户点击隐士打开一个应用程序。
那么,接下去看看startActivity这个过程
Activity的startActivityForResult不管我们是调用startActivity(Intent intent)还是startActivity(Intent intent, Bundle options)最终都会执行到startActivityForResult方法
看看这个方法里面的关键代码
Activity里面的startActivityForResult发现了一个新的类Instrumentation,是这个Instrumentation的实例调用了execStartActivity方法。Instrumentation类是Android操作系统中程序端操作Activity的具体操作类,当系统需要具体执行Activity的某个操作时,都需要借助于Instrumentation来进行具体实现。
Instrumentation的execStartActivity方法再来看关键的代码
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, UserHandle user) {
...
int result = ActivityManagerNative.getDefault() .startActivityAsUser(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options, user.getIdentifier()); checkStartActivityResult(result, intent);
...
}
首先来看看ActivityManagerNative.getDefault是什么
ActivityManagerNative的getDefault方法 ActivityManagerNative的gDefault那么看到IBinder对象,看到asInterface方法,对aidl很熟悉的知道这个IActivityManager很像我们创建的aidl文件,然后ServiceManager.getService("activity")方法返回一个IBinder对象则很像我们连接一个服务,连接成功后返回一个操作服务方法的句柄IBinder,使用asInterface方法可以转换成我们定义的接口对象。
在这里,ActivityManagerNative.getDefault() .startActivityAsUser这个方法实际上就是通过Binder机制进行了跨进程间的通信。为什么在这里需要采用进程间的通信方式呢?因为Android系统里面的应用进程和SystemServer进程不是同一个进程,所以需要采用自身设计的Binder机制。
我们可以回过头来看看ActivityManagerService,发现它是继承ActivityManagerNative的,而ActivityManagerNative是实现IActivityManager接口的,那么最终ActivityManagerNative.getDefault()执行startActivityAsUser这个方法实际上就是执行ActivityManagerService里面的startActivityAsUser方法。
ActivityManagerService里面的startActivityAsUser方法再看看ActivityStarter里面的startActivityMayWait方法,方法很长,节选关键部分
ActivityStarter里面的startActivityLocked方法继续看看startActivityLocked方法,方法同样很长,节选关键部分
ActivityStarter里面的startActivityLocked最终的调用方法注意,调用startActivityUnChecked里面的第一个参数是r,r是ActivityRecord实例,在这个方法里面new了一个ActivityRecord对象,并将这个对象作为参数传入startActivityUnchecked方法里面
调用了方法startActivityUnchecked方法,节选部分
ActivityStarter里面的startActivityUnchecked方法注意,在这里,boolean类型的变量mDoResume为true,这个是之前传入的参数。
继续看ActivityStackSupervisor类里面的resumeFocusedStackTopActivity方法
ActivityStarter里面的resumeFocusedStackTopActivityLocked方法最终调用了targetStack.resumeTopActivityUncheckedLocked方法,看看这个方法
ActivityStack里面的resumeTopActivityUncheckedLocked方法注意,这里是到了ActivityStack里面执行resumeTopActivityUncheckedLocked方法,然后紧接着调用同类里面的resumeTopActivityInnerLocked方法,看看这个方法,方法很长,节选关键部分来看
ActivityStack里面的resumeTopActivityInnerLocked方法我们都知道,在一个活动的Activity里面打开另外一个Activity,那么这个正在活动的Activity必然先经历onPause的生命周期方法。那么在这个地方,不妨可以将startPausingLocked视作要去pause当前的活动Activity。究竟我们的这个猜想是不是正确的,继续跟踪下去。
ActivityStack里面的startPausingLocked方法那么我们在startPausingLocked方法里面找到了一个很重要的调用语句,prev.app.thread.schedulePauseActivity方法,那么这几个prev.app.thread是什么呢?prev是ActivityRecord类型,prev.app是什么呢?从ActivityRecord类结构可以看到,是有个ProcessRecord类,这个类是什么?可以看下它的大致结构
ProcessThread类结构那么很显然,prev.app.thread就是IApplicationThread类型的实例。这个情形有点像IActivityManager的情况。Android系统中,ApplicationThread是IApplicationThread.Stub的子类,那么拥有IApplicationThread对象去执行schedulePauseActivity自然就是执行ApplicationThread里面的schedulePauseActivity方法,是典型的binder通信机制。
继续看下ApplicationThread里面的schedulePauseActivity方法
ActivityThread里面的内部类ApplicationThread那么是调用setMessage方法
ActivityThread里面的sendMessage方法注意,这里的mH是Handler实例。那么再查看消息是怎么被处理的。
handleMessage方法继续看里面调用的handlePauseActivity方法
ActivityThread里面的handlePauseActivity方法继续跟踪下去,performPauseActivity->performPauseActivityIfNeed找到调用的方法
ActivityThread里面的performPauseActivityIfNeed好吧,看到mInstrumentation.callActivityOnPause方法,明白需要借助Instrumentation来调用Activity的方法
Instrumentation里面的callActivityOnPause方法最终回到了Activity里面,看看Activity方法里面的performPause方法
Activity里面的performPause方法其中的onPause就是我们经常写的Activity生命周期方法onPause的调用。
那么到现在为止,我们将Activity栈顶的Activity置为pause状态,那么接下去一步,应该是新的Activity的创建和显示,那么这一步的步骤在哪呢?我们得回到ActivityThread的handlePauseActivity方法里面再看看
还是ActivityThread里面的handlePauseActivity方法上面的红色框是刚才走的流程,将栈顶上面的Activity状态置为pause状态,那么下面的红色框,大家应该很熟悉,binder机制进行进程中的通信,ActivityManager.getService调用activityPaused方法实际上在ActivityManagerService里面具体实现,我们看看这个方法
ActivityManagerService里面实现的activityPaused方法好,接着调用了ActivityStack里面的activityPausedLocked方法
ActivityStack类里面的activityPausedLocked调用了completePauseLocked方法
ActivityStack里面的completePauseLocked方法紧接着,又调用了ActivityStackSupervisor类里面的resumFocusedStackTopActivityLocked方法,看到这个方法名,是不是觉得很熟悉,没错,上面的部分流程和这里是完全一样的。
最终到了ActivityStack里面的resumeTopActivityInnerLocked方法,注意,在此时不会执行startPausingActivityLocked方法,原因是mResumedActivity为null
ActivityStack里面的resumeTopActivityInnerLocked方法不会执行,接着往下走,最终会调用
ActivityStack里面的resumeTopActivityInnerLocked方法继续查看startSpecificActivityLocked方法
ActivityStackSupervisor里面的startSpecificActivityLocked方法注意,这里会有个判断,即判断如果要新建一个进程,则会使用binder方式,调用下面红色框里面的ActivityManagerService里面的startProcessLocked方法;如果不需要新建进程,那么就会执行上面红色框里面的realStartActivityLocked方法。
假设现在的情景是需要新建一个进程,那我们看看ActivityManagerService里面的startProcessLocked方法
ActivityManagerService里面的startProcessLocked方法那么会调用Process.start方法
Process里面的start方法调用方法zygoteProcess.start->startViaZygote->zygoteSendArgsAndGetResult
ZygoteProcess的zygoteSendArgsAndGetResult方法使用Socket方式与Zygote进程进行通信,申请fork了一个新的进程,并根据我们刚刚传递的字段"android.app.ActivityThread",反射出该对象并执行ActivityThread的main方法。所以这个时候新的进程就已经创建好了。我们经常称之ActivityThread为ui线程或者主线程,是因为进程一创建就会首先执行ActivityThread的main方法。
ActivityThread的main方法那么,看到很熟悉的两句代码,Looper.prepareMainLooper和Looper.loop,初始化Looper对象,MessageQueue对象等等,所以我们可以随意在主线程里面new Handler不会报错。
这里,关键句代码thread.attach(false)
ActivityThread里面的attach方法同样,使用binder机制调用了ActivityManagerService的attachApplication方法,attachApplication调用了attachApplicationLocked方法
ActivityManagerService里面的attachApplicationLocked方法调用了ActivityStackSupervisor里面的attachApplicationLocked方法
ActivityStackSupervisor里面的attachApplicationLocked方法到了这里,就是执行realStartActivityLocked方法
ActivityStackSupervisor里面的realStartActivityLocked方法又是通过IApplicationThread的binder机制,调用ActivityThread里面的scheduleLauncherAcitivty方法
ActivityThread里面的scheduleLauncherActivity方法同ActivityThread里面的sendMessage,交由handle来处理消息,最终调用handleLaunchActivity
ActoivityThread里面的handleLaunchActivity方法看到了performLauncherActivity方法,看看是什么
ActivityThread里面的performLaunchActivity的上半部分那么这里的activity是用反射创建出来的,创建好activity之后,看看这个方法的下半部分
ActivityThread里面的performLaunchActivity的下半部分看到第一个红色框,activity.attach方法,在上一篇分析view加载流程的时候说到Window实例mWindow变量就是在attach方法里面初始化的,那么什么时候会调用activity的attach方法呢?答案就在这。
Activity里面的Attach方法第二个红色框,是用mInstrumentation调用callActivityOnCreate方法
Instrumentation里面的callActivityOnCreatef方法 Activity里面的performCreate方法第三个红色框,则是调用了Activity里面的performStart方法
Activity里面的performStart那么onCreate和onStart方法都执行过了,onResume方法什么时候执行呢?这个得回头看看ActivityThread里面的handleLaunchActivity
ActivityThread里面的handleLaunchActivity方法执行了handleResmeActivity
ActivityThread里面的handleResumeActivity在这个方法上半部分,执行了performResumeActivity继而执行activity的performResume方法,到目前为止,新的activity的onResume方法也执行了。那么还有个疑问,已经暂停的activity怎么继续执行它的onStop方法呢?继续在handleResumeActivity的下班部分寻找,有一句关键的代码,上图红色框里面的。
ActivityThread里面的Idler好吧,看到这个,依旧是我们很熟悉的binder对象,调用了ActivityManagerService里面的activityIdle方法
ActivityManagerService里面的activityIdle方法调用了ActivityStackSupervisor里面的activityIdleInternalLocked方法
ActivityStackSupervisor里面的activityIdleInternalLocked方法调用了ActivityStack里面的stopActivityLocked方法
ActivityStack里面的stopActivityLocked方法又是通过binder机制调用了scheduleStopActivity方法
ActivityThread里面的scheduleStopActivity方法最终经过消息的分发,交给handleStopActivity方法处理
ActivityThread里面的handleStopActivity方法调用了performStopActivityInner方法
ActivityThread里面的performStopActivityInner方法回到了Activity里面的peformStop方法
Activity里面的performStop方法借助于mInstrumentation调用callActivityOnStop方法
Instrumentation的callActivityOnStop方法好了,最后一步,调用activity的onStop方法。
总结:
一个Activity的启动都是从startActivity方法开始的,最终都会执行到Activity里面的startActivityForResult,只不过普通的startActivity方法传递的requestCode为-1。
Activity的启动过程是需要SystemServer进程主要是ActivityManagerService代表类和应用进程主要是ActivityThread代表类的共同协助调用的过程。
ActivityThread与ActivityManagerService的沟通需要ActivityManagerNative这个Binder对象,表现为可以在ActvitityThread中调用ActivityManagerService里面的方法。
反过来,ActivityManagerService和ActivityThread的沟通需要ApplicationThread这个Binder对象,表现为可以在ActivityManagerService中调用ActivityThread方法。当然一般而言,不会在ActivityManagerService里面直接调用ActivityThread方法,更多的会在ActivityStarter、ActivityStackSupervisor里面。
当Activity执行到startActivityForResult方法之后,会执行到Instrumentaion里面的execStartActivity方法,这个时候通过Binder机制,会到ActivityManagerService里面去执行。
ActivityManagerService经过一系列的判断,历经ActivityStarter、ActivityStackSupervisor会执行startPausingLocked方法
经过ApplicationThread这个Binder对象,会到ActivityThread里面去执行startPausingActivity方法。
将栈顶的Activity执行onPause方法之后,ActivityThread里面会通过ActivityManagerNative的Binder机制告诉ActivityManagerService继续后续的操作。
ActivityManagerService经过一系列的流转,最终会在ActivityStackSupervisor里面判断,新建的Activity是否需要一个新进程,如果不需要,则执行启动Activity的操作,如果需要,那么还是通过Binder机制通知ActivityManagerService去新建进程。
ActivityManagerService收到了新建进程的消息,通知Process执行start方法,在Process的流程中,通过Socket方式和跟进程Zygote进程沟通,新建一个进程,并且根据传入的进程名字,一般为“android.app.ActivityThread”反射出该对象执行它的main方法。
ActivityThread的main方法里面进行了一些变量的初始化,其中就包括了Looper对象的初始化,然后同样通过Binder机制告诉ActivityManagerService继续接下去的操作。
ActivityManagerService收到之后经过一系列的流转,也是在ActivityStackSupervisor通过Binder机制告诉ActivityThread可以启动新的Activity了。
ActivityThread通过反射机制创建了一个Activity,并借助于Instrumetation完成对新建的Activity的attach、onCreate、onStart和onResume方法,最终执行第一个Activity的onStop方法。