现在的位置: 首页 > 综合 > 正文

activity启动流程

2013年10月07日 ⁄ 综合 ⁄ 共 6108字 ⁄ 字号 评论关闭

先看一下流程图

再有一个是以类图的方式展现的activity启动的流程,可以看到各个类的主要作用

主要函数 分析:

startActivityLocked

1、 getRecordForAppLocked获取调用者的相关信息保存到ProcessRecord变量,这里传递的参数正是前面getApplicationThread获取到的
2、 参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在ActivityRecord变量中
3、 确定sourceRecord和resultRecord,这两个变量均为ActivityRecord类型,前者代表请求启动当前activity的activity;后者表示当前的activity在启动之后需要返回结果的ActivityRecord,一般情况下,如果sourceRecord的activity使用startActivityForResult()启动当前activity并且requestCode>=0时,则resultRecord不为空,且resultRecord=sourceRecord

还有一种特殊的情况,当启动一个activity时,启动的Intent设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志,在这种情况resultRecord并不指向sourceRecord,而是指向sourceRecord的sourceRecord,对比上图

 如上图所示,Activity A 启动了Activity B,Activity B又启动了C,A-->B-->C, 这种情况下,A启动B要求B返回result给A,但是如果B在启动C时,Intent设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志,那么此时将会交由C向A setResult。为了避免冲突,B启动C时不得指定resultRecord>=0。
4、 调用checkComponentPermission对要启动的activity进行一些权限检查
a. Root uid(0), System Server uid (Process.SYSTEM_UID), own process(MY_PID),将授权permission
   b. 如果请求启动的activity的属性android:exported=false, 并且请求的callingUid不等于请求启动的activity的UID,不允许启动;
   c 请求启动的activity没有设定permission,只有当activity的permission和其所在的application的android:permission均为设置时才为null,直设置了application未设置activity,那么activity的permission与application相同。activity的permission为空,则授权;
   d. 请求启动的activity设定了permission,那么检查请求方的activity中是否声明了使用这个permission,如果声明,授权。
5、 构建要启动activity的ActivityRecord结构
6、 调用startActivityUncheckedLocked作进一步的启动操作

startActivityUncheckedLocked
1、 调用getFlags获取intent的标志值,保存在launchFlags变量中
2、 根据标志设置相应的成员变量
mUserLeaving 为true
3、 launchMode有没有设置,里的r.launchMode为默认值0,表示以标准(Standard,或者称为ActivityInfo.LAUNCH_MULTIPLE)的方式来启动这个Activity。Activity的启动方式有四种,其余三种分别是ActivityInfo.LAUNCH_SINGLE_INSTANCE、ActivityInfo.LAUNCH_SINGLE_TASK和ActivityInfo.LAUNCH_SINGLE_TOP
4、 r.resultTo 为null, 不需要等这个即将要启动的Activity的执行结果
5、 sourceRecord的activity的launch mode为ActivityInfo.LAUNCH_SINGLE_INSTANCE,也就是sourceRecord activity的task只允许一个activity;当前activity的launch mode为ActivityInfo.LAUNCH_SINGLE_INSTANCE或者r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK。以上几种情况,均可视为需要为启动的activity创建一个新的task.
6、 如果启动的activity需要新的task,那么新启动的activity将会与其caller断开依赖关系,这个关系主要是指result反馈,A-->B,如果A是通过startActivityForResult()请求启动的,并且requestCode >=0,那么如果B是在新的task中,那么B在finish的时候将不再向A反馈result,而是在启动过程中就会向A反馈一个RESULT_CANCELED
7、 通过对mHistory遍历,查看一下,当前有没有Task可以用来执行这个Activity, 查找可复用的task
8、 调用topRunningNonDelayedActivityLocked检测当前在堆栈顶端的Activity是否就是即将要启动的Activity
9、 需要创建一个新的Task(TaskRecord)来启动这个Activity,mCurTask++
10、 调用addRecentTaskLocked添加到ActivityManagerService的成员mRecentTasks中
11、 调用startActivityLocked

startActivityLocked
1、 将新建的task添加到mHistory
2、 做一些界面管理方面的操作
3、 调用resumeTopActivityLocked进一步操作

resumeTopActivityLocked
1、 调用topRunningActivityLocked获取当前堆栈顶端的Activity,即上步添加进去的
2、 把mUserLeaving的保存在本地变量userLeaving中,然后重新设置为false
3、 看要启动的Activity是否就是当前处理Resumed状态的Activity,如果是的话,那就什么都不用做,直接返回就可以了;否则再看一下系统当前是否休眠状态,如果是的话,再看看要启动的Activity是否就是当前处于堆栈顶端的Activity,如果是的话,也是什么都不用做
4、 mResumedActivity为当前正在执行的activity,不为null,进入startPausingLocked函数

startPausingLocked
1、 把mResumedActivity保存在本地变量prev中
2、 使用Activity的ApplicationThread对象的schedulePauseActivity方法通过它来通知这个Activity它要进入Paused状态了

schedulePauseActivity
这里通过handle message最终调用handlePauseActivity处理

handlePauseActivity
1、 将Binder引用token转换成ActivityRecord的远程接口ActivityClientRecord
2、 调用performUserLeavingActivity函数来调用Activity.onUserLeaveHint通知Activity,用户要离开它了
3、 调用performPauseActivity函数来调用Activity.onPause函数,我们知道,在Activity的生命周期中,当它要让位于其它的Activity时,系统就会调用它的onPause函数
4、 通知ActivityManagerService,这个Activity已经进入Paused状态了,ActivityManagerService现在可以完成未竟的事情,即启动另外一个Activity

activityPaused
1、 通过参数token在mHistory列表中得到要暂停ActivityRecord
2、 如果要暂停的ActivityRecord与mPausingActivity一致,调用completePauseLocked

completePauseLocked
1、 mPausingActivity变量清空
2、 调用resumeTopActivityLocked

resumeTopActivityLocked
1、 topRunningActivityLocked取出要执行的activity
2、 前最后一个Resumed状态的Activity,即Launcher,到了这里已经处于Paused状态了,因此,mResumedActivity为null。最后一个处于Paused状态的Activity为Launcher,因此,这里的mLastPausedActivity就为Launcher。前面我们为MainActivity创建了ActivityRecord后,它的app域一直保持为null
3、 最终调用startSpecificActivityLocked进行下一步操作

startSpecificActivityLocked
1、 取回来的app为null。在Activity应用程序中的AndroidManifest.xml配置文件中,我们没有指定Application标签的process属性,系统就会默认使用package的名称,这里就是"shy.luo.activity"了。每一个应用程序都有自己的uid,因此,这里uid + process的组合就可以为每一个应用程序创建一个ProcessRecord。当然,我们可以配置两个应用程序具有相同的uid和package,或者在AndroidManifest.xml配置文件的application标签或者activity标签中显式指定相同的process属性值,这样,不同的应用程序也可以在同一个进程中启动
Main
1、 创建一个ActivityThread实例,然后调用它的attach函数,接着就进入消息循环了,直到最后进程退出。

Attach
传入了这个ActivityThread的mAppThread

attachApplicationLocked

1、 通过pidProcessRecord取回来,放在app变量中

2、 app的其它成员进行初始化

3、 调用mMainStack.realStartActivityLocked执行真正的Activity启动操作

 

realStartActivityLocked

1、添加到ProcessRecordactivities(一个ProcessRecord对应多个activities)

performLaunchActivity

1、 集要启动的Activity的相关信息,主要packagecomponent信息

2、 通过ClassLoaderActivity类加载进来

3、 创建Application对象,这是根据AndroidManifest.xml配置文件中的Application标签的信息来创建的

4、 主要创建Activity的上下文信息,并通过attach方法将这些上下文信息设置到Activity

5、 还要调用ActivityonCreate函数

 

一个(或多个)Activity对应一个ActivityThread

mInstrumentation:类型是Intrumentation,用来监控应用程序和系统的交互

ActivityStackActivityManagerService处于同一进程

AMS提供了一个ArrayList mHistory来管理所有的activityactivityAMS中的形式是ActivityRecordtaskAMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord。如下图所示


从图中我们可以看出如下几点规则:
    1. 所有的ActivityRecord会被存储在mHistory管理;
    2. 每个ActivityRecord会对应到一个TaskRecord,并且有着相同TaskRecord的ActivityRecord在mHistory中会处在连续的位置(一般是在同一个apk中启动到不同的activity,在start流程中startActivityUncheckedLocked会设置为当前活动activity的TaskRecord);
    3. 同一个TaskRecord的Activity可能分别处于不同的进程中,每个Activity所处的进程跟task没有关系;(ProcessRecord 标识以processName+ uid,可以配置两个activity的application标签这两个值一样)


引用老罗中的总结,整个启动步骤



  一. Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
  二. ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
三.Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,
四.ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行;
五.ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
六.ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了


参考:

http://blog.csdn.net/luoshengyang/article/details/6689748

http://gamebs.blog.163.com/blog/static/1860182182012511378416/

抱歉!评论已关闭.