Activity组件启动过程分析
2016-12-03 22:49
246 查看
本文参考
1. Gityuan博文:startActivity启动过程分析
2. 老罗博文:Activity组件的启动过程
整理文档 网盘地址:https://pan.baidu.com/s/1hrEn2O8
从应用程序的角度出发,我们可以将Activity组件划分为两种类型:一种是根Activity,另一种是子Activity。根Activity以快捷图标的形式显示在应用程序启动器中,它的启动过程就代表了一个Android应用程序的启动过程。子Activity由根Activity或者其他子Activity启动,它们有可能与启动它们的Activity运行在同一个进程中,也有可能运行在不同的进程中,这取决于它们的配置和启动参数。
Activity组件的启动方式分为显示和隐式两种。对于显示启动的Activity组件来说,我们必须事先知道用来实现它们的类的名称; 而对于隐式启动的Activity组件来说,我们只需要知道它们的组件名称即可,而不需要知道它们是由哪一个类来实现的。无论是显示启动的Activity组件,还是隐式启动的Activity组件,它们的启动过程都是类似的,唯一的区别在于系统是根据类名还是组件名称来找到它们。但是从软件工程的角度来看,隐式启动Activity组件可以减少Android应用程序组件间的依赖。
该指令可以查看栈中Activity列表,包含了task等信息。从下面的图一来看,当前只有一个任务栈#0,栈中有两个任务,任务#3是我们直观可见的Launcher,任务#4是长按任务键可见的最近任务列表。这种情况是默认的场景。
图1、默认场景
图2、Launcher启动My Test应用
根Activity:
子Activity:
从上面的图2来看,MainActivity位于任务栈#1中,运行在进程com.example.calf1234.mainprocess/u0a57中,与Launcher组件所处的进程不同。换而言之,启动Main Activity需要创建一个新的进程。本章节将根据events log来分析根Activity的启动过程。
图3、My Test启动events log
从events log来看,大致可推出MainActivity的启动过程:
1、Launcher组件向AMS发送一个启动MainActivity组件的进程间通信请求。
2、AMS(ActivityManagerService)首先将要启动的MainActivity组件的信息保存下来,然后再向Launchr组件发送一个进入中止状态的进程间通信请求。
3、Launcher组件进入到中止状态之后,就会向AMS发送一个已进入中止状态的进程间通信请求,以便AMS可以继续执行启动MainActivity组件的操作。
4、AMS发现用来运行MainActivity组件的应用程序进程不存在,因此,它就会先启动一个新的应用程序进程。
5、新的应用程序进程启动完成之后,就会向AMS发送一个启动完成的进程间通信请求,以便AMS可以继续执行启动MainActivity组件的操作。
6、AMS将step 2保存下来的Main Activity组件的信息发送给step 4创建的应用程序进程,以便它可以将MainActivity组件启动起来。
图4、Activity组件启动流程图
step5. 给intent设置了FLAG_ACTIVITY_NEW_TASK标志位。此标志位意味着一般从Launcher启动应用都会新建一个调用栈,除非之前有遗留的未被销毁的调用栈。
step6. 默认的requestcode值为-1,即不返回结果。
Step8.
在Instrumentation.java文件中有三个execStartActivity方法,在Activity类中调用此方法2。重要参数:
contextThread:传递进来的为类型ApplicationThead的IBinder对象,实际上代表Launcher组件所运行的应用程序进程。
Token:传递进来的是一个IBinder代理对象,该对象指向了AMS中对应的ActivityRecord对象,即保存有Launcher组件信息。
target:Activity对象,这里指的是Launcher组件。
intent:携带即将要启动的组件的信息,这里指的是MainActivity组件。
与1的差别在于param4,1中为Activity对象,2中则为String对象。
step9. 此步骤,Launcher进程开始通过AMS代理对象与AMS进行Binder进程间通信。换而言之,Launcher组件向AMS发送一个启动MainActivity组件的进程间通信请求。
step1. 将需奥传递的数据封装成Parcel对象,、通过Binder进程间通信机制与AMS进行交互,附带子命令:START_ACTIVITY_TRANSACTION。
step2. 重点关注caller、intent、resultTo参数。
step5、6. 通过PMS获取最匹配intent的组件,此处代表的是即将要启动的MainActivity组件详细信息。
step7. 在AMS中新建与即将要启动的MainActivity组件相对应的ActivityRecord对象。
step8. 方法一开始进行一些初始化操作,主要还是为intent进一步设置标志位,同时根据标志位做一些特定地操作,比如新建任务栈。
之前设置了FLAG_ACTIVITY_NEW_TASK标志位,这里会新建一个task。
这里对上了一部分的events log。
step11. 在启动MainActivity组件的过程中发现Launcher组件并没有pausing。
step12. 此时此刻向Launchr组件发送一个进入中止状态的进程间通信请求,同时在events log中输出Launcher组件am_pause_activity信息。
step2. 利用Handler沟通ApplicationThread与ActivityThread。
step6. 该方法内通过调用Instrumentation类的callActivityOnPause方法来中止Launcher组件,执行完该代码后,events log中会输出am_on_pause_called信息。
step8. 6804行代码很熟悉,会调用自己继承Activity类重写的方法onPause。
step9. Launcher组件自己中止OK后,通知AMS继续启动MainActivity组件。
step4. 继续启动MainActivity组件。
step7. MainActivity组件对应的ProcessRecord和ApplicationThread对象不存在。
step8. 基于step7,发现MainActivity组件所属的进程不存在,故先去创建进程。
step4. 通知zygote fork一个子进程,返回的ProcessStartResult结果带有pid进程号。
step15. BindApplication时,创建context、Instrumentation、Application类型对象。
step1. 获取即将要启动的MainActivity组件。
此时hr值不为空,故调用realStartActivityLocked方法去启动MainActivity组件。
step3. 通知My Test应用程序进程去启动MainActivity组件。
1. Gityuan博文:startActivity启动过程分析
2. 老罗博文:Activity组件的启动过程
整理文档 网盘地址:https://pan.baidu.com/s/1hrEn2O8
Activity
Activity是Android应用程序的四大组件之一,它负责管理Android应用程序的用户界面。一个应用程序一般会包含若干个Activity组件,每一个Activity组件负责一个用户界面的展现,它们可能运行在同一个进程中 ,也可能运行在不同的进程中。运行在不同进程中的Activity组件通过Binder进程间通信机制来协作完成应用程序的功能。从应用程序的角度出发,我们可以将Activity组件划分为两种类型:一种是根Activity,另一种是子Activity。根Activity以快捷图标的形式显示在应用程序启动器中,它的启动过程就代表了一个Android应用程序的启动过程。子Activity由根Activity或者其他子Activity启动,它们有可能与启动它们的Activity运行在同一个进程中,也有可能运行在不同的进程中,这取决于它们的配置和启动参数。
Activity组件的启动方式分为显示和隐式两种。对于显示启动的Activity组件来说,我们必须事先知道用来实现它们的类的名称; 而对于隐式启动的Activity组件来说,我们只需要知道它们的组件名称即可,而不需要知道它们是由哪一个类来实现的。无论是显示启动的Activity组件,还是隐式启动的Activity组件,它们的启动过程都是类似的,唯一的区别在于系统是根据类名还是组件名称来找到它们。但是从软件工程的角度来看,隐式启动Activity组件可以减少Android应用程序组件间的依赖。
根Activity组件的启动过程
指令:adb shell dumpsys activity activities该指令可以查看栈中Activity列表,包含了task等信息。从下面的图一来看,当前只有一个任务栈#0,栈中有两个任务,任务#3是我们直观可见的Launcher,任务#4是长按任务键可见的最近任务列表。这种情况是默认的场景。
图1、默认场景
图2、Launcher启动My Test应用
前言介绍:
My Test应用根Activity为MainActivity,拥有两个子Activity。MainActivity与SubActivity1运行在同一个进程中,而SubActivity2处于不同的进程中。从Launcher点击启动My Test应用,默认启动MainActivity。结合图1、2来看,由于之前没有启动过,此次启动MainActivity会创建一个新的任务栈,即任务栈#1,栈中只运行了一个根Activity。根Activity:
子Activity:
从上面的图2来看,MainActivity位于任务栈#1中,运行在进程com.example.calf1234.mainprocess/u0a57中,与Launcher组件所处的进程不同。换而言之,启动Main Activity需要创建一个新的进程。本章节将根据events log来分析根Activity的启动过程。
图3、My Test启动events log
从events log来看,大致可推出MainActivity的启动过程:
1、Launcher组件向AMS发送一个启动MainActivity组件的进程间通信请求。
2、AMS(ActivityManagerService)首先将要启动的MainActivity组件的信息保存下来,然后再向Launchr组件发送一个进入中止状态的进程间通信请求。
3、Launcher组件进入到中止状态之后,就会向AMS发送一个已进入中止状态的进程间通信请求,以便AMS可以继续执行启动MainActivity组件的操作。
4、AMS发现用来运行MainActivity组件的应用程序进程不存在,因此,它就会先启动一个新的应用程序进程。
5、新的应用程序进程启动完成之后,就会向AMS发送一个启动完成的进程间通信请求,以便AMS可以继续执行启动MainActivity组件的操作。
6、AMS将step 2保存下来的Main Activity组件的信息发送给step 4创建的应用程序进程,以便它可以将MainActivity组件启动起来。
图4、Activity组件启动流程图
1.Launcher通知AMS启动MainActivity
step5. 给intent设置了FLAG_ACTIVITY_NEW_TASK标志位。此标志位意味着一般从Launcher启动应用都会新建一个调用栈,除非之前有遗留的未被销毁的调用栈。
step6. 默认的requestcode值为-1,即不返回结果。
Step8.
在Instrumentation.java文件中有三个execStartActivity方法,在Activity类中调用此方法2。重要参数:
contextThread:传递进来的为类型ApplicationThead的IBinder对象,实际上代表Launcher组件所运行的应用程序进程。
Token:传递进来的是一个IBinder代理对象,该对象指向了AMS中对应的ActivityRecord对象,即保存有Launcher组件信息。
target:Activity对象,这里指的是Launcher组件。
intent:携带即将要启动的组件的信息,这里指的是MainActivity组件。
与1的差别在于param4,1中为Activity对象,2中则为String对象。
step9. 此步骤,Launcher进程开始通过AMS代理对象与AMS进行Binder进程间通信。换而言之,Launcher组件向AMS发送一个启动MainActivity组件的进程间通信请求。
2.保存MainActivity信息,后通知Launcher中止
step1. 将需奥传递的数据封装成Parcel对象,、通过Binder进程间通信机制与AMS进行交互,附带子命令:START_ACTIVITY_TRANSACTION。
step2. 重点关注caller、intent、resultTo参数。
step5、6. 通过PMS获取最匹配intent的组件,此处代表的是即将要启动的MainActivity组件详细信息。
step7. 在AMS中新建与即将要启动的MainActivity组件相对应的ActivityRecord对象。
step8. 方法一开始进行一些初始化操作,主要还是为intent进一步设置标志位,同时根据标志位做一些特定地操作,比如新建任务栈。
之前设置了FLAG_ACTIVITY_NEW_TASK标志位,这里会新建一个task。
这里对上了一部分的events log。
step11. 在启动MainActivity组件的过程中发现Launcher组件并没有pausing。
step12. 此时此刻向Launchr组件发送一个进入中止状态的进程间通信请求,同时在events log中输出Launcher组件am_pause_activity信息。
3.Launcher中止OK,通知AMS继续启动
step2. 利用Handler沟通ApplicationThread与ActivityThread。
step6. 该方法内通过调用Instrumentation类的callActivityOnPause方法来中止Launcher组件,执行完该代码后,events log中会输出am_on_pause_called信息。
step8. 6804行代码很熟悉,会调用自己继承Activity类重写的方法onPause。
step9. Launcher组件自己中止OK后,通知AMS继续启动MainActivity组件。
4.AMS继续启动MainActivity组件
step4. 继续启动MainActivity组件。
step7. MainActivity组件对应的ProcessRecord和ApplicationThread对象不存在。
step8. 基于step7,发现MainActivity组件所属的进程不存在,故先去创建进程。
5.AMS为MainActivity组件创建新进程
step4. 通知zygote fork一个子进程,返回的ProcessStartResult结果带有pid进程号。
step15. BindApplication时,创建context、Instrumentation、Application类型对象。
6.进程创建OK,继续启动MainActivity组件
step1. 获取即将要启动的MainActivity组件。
此时hr值不为空,故调用realStartActivityLocked方法去启动MainActivity组件。
step3. 通知My Test应用程序进程去启动MainActivity组件。
相关文章推荐
- Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)
- Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析
- Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)
- Android系统源码阅读(2):根Activity组件的启动过程
- 【Android - 组件】之Activity的启动模式
- Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析
- Android基础总结.doc(第六节、 Activity组件的启动模式、广播、服务组件 )
- Android核心基础-8.Android四大组件之Activity-3.生命周期、横竖屏切换、启动模式、进程管理
- Android Activity组件的启动过程
- Android四大组件——Activity生命周期、启动模式、显隐式意图、杀死进程、杀死所有Activity、安装及反编译
- Android的四大组件之三--Activity(4)----->Activity的启动方式和相关参数
- Activity组件的启动过程
- Intent启动系统组件(activity,service,BroadReceiver)-android学习之旅(四十九)
- Activity组件启动过程(三)
- 深入剖析Android四大组件(七)——Activity启动的4个阶段
- Android源码解析四大组件系列(二)---Activity启动过程的总体把握
- Android四大组件Activity启动源码分析
- Android Activity组件的启动过程
- Android四大组件之Activity(四种基本启动模式)
- [看书日记20160104]四大组件的工作过程, Activity的生命周期和启动模式