无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。
 解释:没有专心致志地刻苦学习,就没有融会贯通的智慧;没有埋头执着的工作,就不会取得显著的成就。

Activity启动流程

   提到Activity的启动,之前也简单看过一点,当时以为整个流程是从ActivityThread开始的,因为那里有个main方法,就像平常写Java代码的入口一样,从main开始。后来慢慢的了解多了,发现那只是一部分而已。而且之前看的时候,只是走了一遍代码方法流程,根本不知道这个方法是干什么的,哪个方法是干什么的。有时候,被问到Activity启动流程的时候,都会哑口无言,因为不知道从哪里开始,总不能回答从main开始调用了哪些方法吧,这方法太多了,记也记不住。突然对学习源码有了一些思考。

  1. 需要知道源码的代码是干什么的?首先清楚是做了什么事情?
  2. 为了做这些事情,写源码的人是怎么设计代码的?
  3. 为什么这么设计?有什么好处?

   这次再看源码,因为设计的代码实在太多了,要全面理解那可太难了,好像第一点都不能完全做好。但是这次起码要理清楚在Activity启动流程中涉及到了哪些进程,在这些进程中,哪些进程做了哪些事情以及进程间使用哪种通信方式。

   Activity的启动流程有两种,一种是进程内启动,一种是需要创建新的进程。网上这方面的文章非常多,但是大多数文章都是贴一大堆的代码,看得眼花缭乱。不过Activity的启动流程确实涉及到非常非常多的代码,这几天看源码也是看的很累。所以这篇文章不会放代码,写这篇文章的目的就是理清Activity启动过程的一些重点部分,所以只会提到涉及的方法名以及这些方法的作用。

   这里先整理需要创建新进程的那种。以Launcher启动一个应用(App)为例。

   这种需要创建新进程的启动Activity的流程,会涉及到四个进程,所以大致分为四个阶段:

  1. 发起进程:启动Activity(也就是Launcher)所在的进程,跨进程通信通知ActivityManagerService需要启动一个Activity
  2. System_Server进程:ActivityManagerService根据接收到的参数,处理一系列与Activity相关的事情
  3. Zygote进程:ActivityManagerService通过Socket进程间通信,通知Zygote进程fork出一个新的进程
  4. 新创建的应用进程:通过与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

   到这,整个流程就结束了。

results matching ""

    No results matching ""