无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。
解释:没有专心致志地刻苦学习,就没有融会贯通的智慧;没有埋头执着的工作,就不会取得显著的成就。
Activity启动流程
提到Activity的启动,之前也简单看过一点,当时以为整个流程是从ActivityThread开始的,因为那里有个main方法,就像平常写Java代码的入口一样,从main开始。后来慢慢的了解多了,发现那只是一部分而已。而且之前看的时候,只是走了一遍代码方法流程,根本不知道这个方法是干什么的,哪个方法是干什么的。有时候,被问到Activity启动流程的时候,都会哑口无言,因为不知道从哪里开始,总不能回答从main开始调用了哪些方法吧,这方法太多了,记也记不住。突然对学习源码有了一些思考。
- 需要知道源码的代码是干什么的?首先清楚是做了什么事情?
- 为了做这些事情,写源码的人是怎么设计代码的?
- 为什么这么设计?有什么好处?
这次再看源码,因为设计的代码实在太多了,要全面理解那可太难了,好像第一点都不能完全做好。但是这次起码要理清楚在Activity启动流程中涉及到了哪些进程,在这些进程中,哪些进程做了哪些事情以及进程间使用哪种通信方式。
Activity的启动流程有两种,一种是进程内启动,一种是需要创建新的进程。网上这方面的文章非常多,但是大多数文章都是贴一大堆的代码,看得眼花缭乱。不过Activity的启动流程确实涉及到非常非常多的代码,这几天看源码也是看的很累。所以这篇文章不会放代码,写这篇文章的目的就是理清Activity启动过程的一些重点部分,所以只会提到涉及的方法名以及这些方法的作用。
这里先整理需要创建新进程的那种。以Launcher启动一个应用(App)为例。
这种需要创建新进程的启动Activity的流程,会涉及到四个进程,所以大致分为四个阶段:
- 发起进程:启动Activity(也就是Launcher)所在的进程,跨进程通信通知ActivityManagerService需要启动一个Activity;
- System_Server进程:ActivityManagerService根据接收到的参数,处理一系列与Activity相关的事情;
- Zygote进程:ActivityManagerService通过Socket进程间通信,通知Zygote进程fork出一个新的进程
- 新创建的应用进程:通过与ActivityManagerService通信,拿到需要启动的Activity的信息,然后启动Activity。
一、发起进程(Launcher所在的进程)
Launcher.java 父类:Activity (它们不再一个包下面)
做的事情很简单,点击需要启动的App的图标的时候,在对应的点击事件回调的onClick方法。
- 回调onClick:拿到被启动的Activity的信息(Intent),然后调用startActivitySafely方法,
- startActivitySafely,紧接着调用自己的startActivity方法
- startActivity:这个方法好像是检查一下是不是要忽略启动动画,然后选择调用父类Activity的哪个startActivity方法,区别是:传不传一个Bundle对象。这个Bundle对象好像是与Activity切换动画相关的。
Activity.java
- startActivity:紧接着调用startActivityForResult,多传了一个参数:-1,表示不需要被启动Activity退出的时候,不需要返回结果。
- startActivityForResult:判断mParent是否为空,这里是为空的,然后调用Instrumentation的execStartActivity方法。传过去的参数:
- this : Context类型,当前对象,也就是launcher
- mMainThread.getApplicationThread:IBinder类型,主线程的ApplicationThread,用来跨进程跟ActivityManagerService通信
- mToken :IBinder类型,用来标识谁启动这个Activity
- this :Activity类型,当前对象,也就是launcher
- intent:Intent类型,被启动的Activity的信息
- requestCode:int类型,请求码,这里是-1
- options:Bundle类型,Activity切换动画相关
Instrumentation.java
- execStartActivity:拦截已经启动的Activity,然后调用ActivityManager.getService().startActivity方法。传过去的参数:
- whoThread:IApplicationThrad类型,其实就是上面传过来的mMainThread.getApplicationThread去掉IBinder跨进程通信功能。这个熟悉Bindler进程间通信,就知道这是基本操作了。
- who.getBasePackageName:String类型,who是上面的startActivityForResult方法传过来的第一参数,这里应该是Launcher的包名。
- intent:Intent类型,被启动的Activity的信息
- intent.resolveTypeIfNeed(who.getContentResolver):String类型,
- token:IBinder类型,用来标识谁启动这个Activity
- target!=null?target.mEmbeddedID:null:String类型,
- requestCode:int类型,请求码,这里是-1
- 0:int类型,
- null:ProfilerInfo类型,
- options:Bundle类型,Activity切换动画相关 代码运行到这里之后,进程就从Launcher进程切换到了System_Server进程了,切换的方式是Binder进程间通信。这里涉及到ActivityManager与ActivityManagerService之间的Binder机制,不展开了。
二、System_Server进程
在这个进程里,其实主要是ActivityManagerService起作用。
ActivityManagerService.java
- startActivity:紧接着调用startActivityAsUser,没有其他操作
- startActivityAsUser:权限检查,判断当前用户有没有权限启动Activity,及检查其他安全权限。接着调用ActivityStarter的startActivityMayWait,传过去的参数:
- caller:IApplicationThrad类型,
- -1:
- callingPackage:String类型,Launcher的包名
- intent:Intent类型,被启动的Activity的信息
- resolvedType:String类型
- null:
- null:
- resultTo:IBinder类型,就是上面的token,用来标识谁启动这个Activity
- resultWho:String类型,Launcher的mEmbeddedID
- requestCode:int类型,请求码,这里是-1
- startFlags:int类型,这里是0
- profilerInfo:ProfilerInfo类型,这里是null
- null:WaitResult类型,参数名outResult
- null:Configuration类型,参数名 globalConfig
- bOptions:Bundle类型,Activity切换动画相关
- false:boolean类型,参数名:ignoreTargetSecurity
- userId:int类型,启动Activity的UserID
- null:TaskRecord类型,参数名 inTask
- "startActivityAsUser":String类型,参数名reason,好像是启动原因
ActivityStarter.java
startActivityMayWait:这个方法具体干嘛的不太了解。大概会做一些被启动Activity的信息整理。接着调用startActivityLocked传过去的参数:
- IApplicationThread caller 沿用
- Intent intent 。 沿用
- Intent ephemeralIntent
- String resolvedType 沿用
- ActivityInfo aInfo 被启动的Activity的信息
- ResolveInfo rInfo
- IVoiceInteractionSession voiceSession
- IVoiceInteractor voiceInteractor
- IBinder resultTo 沿用
- String resultWho 。 沿用
- int requestCode 。 沿用 -1
- int callingPid
- int callingUid
- String callingPackage 沿用 Launcher的包名
- int realCallingPid
- int realCallingUid
- int startFlags 沿用 0
- ActivityOptions options 沿用
- boolean ignoreTargetSecurity
- boolean componentSpecified
- ActivityRecord[] outActivity new ActivityRecord[1]
- TaskRecord inTask : 沿用 null
- String reason : 沿用
startActivityLocked:这个方法检查一下,上面的reason是否为空,为空抛异常。然后调用startActivity方法
startActivity:这个方法会处理一些Activity的启动模式相关的操作及创建ActivityRecord等相关操作,大部分没看懂。。。最后返回调用重载的startActivity方法,传过去的参数:
- ActivityRecord r 新创建的
- ActivityRecord sourceRecord 应该是Launcher所对应的ActivityRecord
- IVoiceInteractionSession voiceSession 不懂干嘛的
- IVoiceInteractor voiceInteractor 不懂干嘛的
- int startFlags 沿用 0
- boolean doResume true
- ActivityOptions options 沿用,Activity切换动画相关
- TaskRecord inTask 。 变化了
- ActivityRecord[] outActivity : 里面的值与第一个参数r是一样的
- startActivity(重载):紧接着调用startActivityUnchecked方法,传过去的参数跟上面一样
startActivityUnChecked:这是一个比较重要的方法。在这个方法里面处理Activity的启动模式及是否需要创建新的TaskRecord等。根据最终处理的策略,将需要启动的Activity,以及相关的TaskRecord、ActivityStack、ActivityDisplay作出处理。对于本次启动Activity,因为是第一次启动应用,所以ActivityRecord、ActivityStack、ActivityDisplay都需要创建。下面是调用的方法:
- 1、setInitalState,初始化一些参数,比如mDoResume值等于参数doResume,也就是true。mStartActivity设置为参数r,也就是要启动的Activity。
- setTaskFromReuseOrCreateNewTask,调用computeStackFocus,创建ActivityStack:mTargetStack。调用mTargetStack.createTaskRecord,创建TaskRecord。调用addOrReparentStartingActivity
- 1、computeStackFocus调用ActivityStackSupervisor.getStack来创建ActivityStack
- 2、ActivityStackSupervisor.getStack: 调用createOnDisplay
- 3、ActivityStackSupervisor.createOnDisplay:调用getActivityDisplayOrCreateLocked,再调用createStack
- 4、ActivityStackSupervisor.getActivityDisplayOrCreateLocked:new一个ActivityDisplay,放到mActivityDisplays里面
- 5、ActivityStackSupervisor.createStack,返回new ActivityStack
- 6、ActivityStack构造方法:调用postAddToDisplay,把创建出来的ActivityStack放到当前的ActivityDisplay的mStacks列表中。
- 1、ActivityStack.createTaskRecord:mTargetStack调用createTaskRecord,创建TaskRecord。
- 1、ActivityStarter.addOrReparentStartingActivity:把要启动的Activity放到新建的TaskRecord的顶部,调用TaskRecord的addActivityToTop
- 2、TaskRecord.addActivityToTop:调用addActivityAtIndex
- 3、TaskRecord.addActivityAtIndex,把ActivityRecord放到mActivities里面
- 0、ActivityStack.startActivityLocked,里面再调用insertTaskAtTop,把要创建出来的TaskRecord放到mTaskHistroy里面
- 0、ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
ActivityStackSupervisor:
- resumeFocusedStackTopActivityLocked:紧接着调用ActivityTask的resumeTopActivityUncheckedLocked方法
ActivityTask.java:
- resumeTopActivityUncheckedLocked:紧接着调用resumeTopActivityInnerLocked方法
- resumeTopActivityInnerLocked:这个方法将当前显示的Activity执行pause操作,然后调用ActivityStackSupervisor的startSpecificActivityLocked方法
ActivityStackSuperviso.java
- startSpecificActivityLocked:在这个方法中,分两种情况:1、要启动的Activity进程已经起来的话,调用realStartActivityLocked方法。2、要启动的Activity进程不存在,那就调用ActivityManagerService的startProcessLocked方法,创建进程。
ActivityManagerService.java
- startProcessLocked:有几个重载方法。最终都调用同一个,这个方法主要设置好参数,然后调用Process的start方法,接收并处理Socket进程间通信返回的结果
Process.java
- start:紧接着调用ZygoteProcess的start方法
ZygoteProcess.java
- start
- startViaZygote:设置参数。调用openZygoteSocketIfNeed,把返回结果最为参数继续调用zygoteSendArgsAndGetResult
- openZygoteSocketIfNeed:调用ZygoteState的connect,通过Socket进程间通信,与Zygote进程取得联系,返回ZygoteState类型
- zygoteSendArgsAndGetResult:从参数ZygoteState中获取读写流,把参数按一行一个的形式写到Zygote进程。然后读取返回的数据。
三、Zygote进程
Zygote进程是Android中Java世界或者说用户空间的第一个进程。系统启动会在内核空间拉起init进程,之后init进程再拉起Zygote进程。Zygote进程启动之后,在main方法会首先fork出System_Server进程,然后调用ZygoteServer的runSelectLoop,启动一个Socket服务端,一直等待客户端请求创建进程。
这里需要留意的是,在processOneCommand方法获取返回值的时候,新进程fork已经出来了,而新进程是复制Zygote进程的,所以两个进程当前都运行在各自的processOneCommand方法里,不过两个进程的processOneCommand获得的返回值不一样。子进程获得的是0;
ZygoteInit.java
- main,调用ZygoteServer的runSelectLoop方法,接收一个Runnable,返回不为空调用它的run方法。
ZygoteServer.java
- runSelectLoop:循环等待客户端请求,当客户端请求过来的时候,创建ZygoteConnection,并调用processOneCommand方法
ZygoteConnection.java
- processOneCommand:调用Zygote.forkAndSpecialize方法fork进程。这个方法要注意,获取返回结果的时候,已经fork出新进程了,如果返回值是0,掉用handleChildProc;否则调用handleParentProc。
Zygote.java
- forkAndSpecialize:进入底层fork进程,因为Zygote进程fork进程是复制自身,所以这个方法会“返回两次”。返回两次的说法我觉得不妥,因为返回的时候实际上已经fork出了新进程了,这两次返回时在不同的进程的。执行到这,Zygote的任务就完成了。
四、新创建的进程(App进程)
这个进程由复制Zygote进程而的,所以一开始是运行在processOneCommand方法。
ZygoteConnection.java
- processOneCommand:获得返回值是0,然后调用handleChildProc方法,获得返回的Runnable对象之后调用run方法
- handleChildProc:这个方法断开Socket连接,回收连接资源。然后调用ZygoteInit.zygoteInit
ZygoteInit.java
- zygoteInit:调用RuntimeInit的applicationInit方法
RuntimeInit.java
- applicationInit:参数封装成Arguments类对象,调用findStaticMain方法。
- findStaticMain:反射机制获得ActivityThread的main方法,封装成MethodAndArgsCaller
MathodAndArgsCaller:RuntimeInit的内部类,实现Runnable接口,run方法中通过反射调用ActivityThread的main方法。这个run方法是在processOneCommand中调用。
ActivityThread.java
终于回到这里了!!!!!!!!!!!!
- main:调用Looper.prepareMainLooper。创建ActivityThread对象,调用这个对象的attach方法。调用Looper.loop开启消息循环机制。
- attach:这里主要看,ActivityManager.getService获取ActivityManagerService的代理对象,然后调用ActivityManagerService的attachApplication方法,参数是ApplicationThread,ApplicationThread具有Binder进程间通信能力,用于ActivityThread跟ActivityManagerService通信。
Looper.java
- prepareMainLooper:创建主线程的Looper消息循环机制的相关内容:Looper对象,MessageQueue等。
- looper:开启循环机制
ActivityManagerService.java: 切换到System_Server进程
- attachApplication:紧接着调用attachApplicationLocked
- attachApplicationLocked:调用Application的bindApplication绑定Application的信息,这个调用又切换回了新创建的进程进行。然后调用ActivityStackSupervisor的attachApplicationLocked方法。
ActivityStackSupervisor.java
- attachApplicationLocked:遍历mActivityDisplays,找到每个ActivityDisplay的mStacks列表,再遍历mStacks,找到所有的ActivityStack,调用ActivityStack的getAllRunningVisbleActivitiesLocked,找到所有的TaskRecord,再调用TaskRecord的getAllRunningVisableActivitiesLocked,找到所有要启动的Activity。最后调用realStartActivityLocked
- realStartActivityLocked:这个方法有调用app.thread.scheduleLaunchActivity,又回到了新创建的进程。
ActivityThread.java: app进程
- ApplicationThread 类 ActivityThread的内部类 scheduleLaunchActivity:整理参数,调用sendMessage方法,发送LAUNCH_ACTIVIYT类型消息 sendmessage:这个方法会用Activitythread的成员变量mH发送消息到主线程消息循环机制,在这里后续会调用handleLaunchActivity
- handleLaunchActivity:调用preformLaunchActivity创建Activity
- preformLaunchActivity:通过Instrumentation对象,调用newActivity方法,使用反射机制创建一个Activity。然后调用callActivityOnCreate
Instrumentation.java
- newActivity:反射机制,创建Activity
- callActivityOnCreate:调用创建出来的Activity的preformCreate方法
Activity.java
- preformCreate:在这调用Activity的onCrate
到这,整个流程就结束了。