Activity启动过程中需要注意的一些类:

  • Instrumentation     完成对Application和Activity初始化和生命周期调用的工具类。用来监控系统与应用的交互。
  • ActivityThread     管理应用进程的主线程的执行。
  • ApplicationThread     用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService管理应用进程中的Activity时,通过ApplicationThread的代理对象与ActivityThread通讯。(继承IApplicationThread.Stub)
  • ActivityClientRecord     在应用程序进程中启动的每一个Activity组件都使用一个ActivityClientRecord对象来描述。并且保存在ActivityThread类的成员变量mActivities中。
  • ActivityRecord     在AMS进程中,一个ActivityRecord对应一个Activity,保存了一个Activity的所有信息。这些ActivityRecord对象对应于App进程中的ActivityClientRecord。
  • TaskRecord   任务栈,每一个TaskRecord都可能存在一个或多个ActivityRecord,栈顶的ActivityRecord表示当前可见的界面 。
  • ActivityStack    一个栈式管理结构,每一个ActivityStack都可能存在一个或多个TaskRecord,栈顶的TaskRecord表示当前可见的任务。
  • ActivityStackSupervisor     管理着多个ActivityStack,但当前只会有一个获取焦点(Focused)ActivityStack。 ProcessRecord     记录着属于一个进程的所有ActivityRecord,运行在不同TaskRecord中的ActivityRecord可能是属于同一个 ProcessRecord。
  • ActivityManagerService     AMS主要负责系统中四大组件的启动、切换、及进程的管理和调度等工作,Android8.0中AMS继承IActivityManager.Stub。

Activity启动,从Launcher到AMS

Activity类的成员变量mMainThread的类型为ActivityThread,用来描述一个应用程序进程。系统每当启动一个应用程序进程时,都会在它里面加载一个ActivityThread实例,并且会将这个ActivityThread类实例保存在每一个在该进程中启动的Activity组件的父类Activity的成员变量mMainThread中。(该进程中每一个启动的Activity都会保存一个ActivityThread实例)

ActivityThread类的成员函数getApplicationThread()用来获取它内部的一个类型为ApplicationThread的BInder本地对象。

将Luncher组件所运行在的应用程序进程的ApplicationThread对象作为参数传递给成员变量mInstrumentation的成员函数execStartActivity,以便可以将它传递给ActivityManageService,这样ActivityManageService 可以通知Launcher组件进入Pause状态。

Activity类的成员变量mToken的类型是IBinder,它是一个Binder代理对象,指向了ActivityManageService 中一个类型为 ActivityRecord的Binder本地对象,用来维护对应的Activity组件的运行状态以及信息。(并且这个mToken对象是在Activity的attach方法中赋值的)

Launcher组件的成员变量mToken作为参数传递给成员变量mInstrumentation的成员函数execStartActivity, 以便可以将其传递给ActivityManagerService,这样ActivityManagerService接下来就可以获得Launcher组件的详细信息了。

  • ApplicationThread和mToken(IBinder)

这两个参数比较重要,ApplicationThread参数最终会交给ActivityManagerService,ActivityManagerService会通过ApplicationThread来通知Launcher组件等状态变化,比如进入Paused状态。

mToken是IBinder类型,他是一个Binder代理对象,这个mToken最终会交给ActivityManagerService,通过mToken获取Launcher组件的详细信息。(这个mToken中封装了ActivityRecord对象)。

  • ActivityManager.getService()获取ActivityManagerService对象

Activity类的成员变量mToken的类型是IBinder,它是一个Binder代理对象,指向了ActivityManageService 中一个类型为 ActivityRecord的Binder本地对象,用来维护对应的Activity组件的运行状态以及信息。(并且这个mToken对象是在Activity的attach方法中赋值的)。

(每一个已经启动的Activity组件在ActivityManagerService中都有一个对应的ActivityRecord对象,用来维护对应的Activity组件的运行状态和信息)。

通过单例模式获取ActivityManagerService到代理。

  public static IActivityManager getService() {return IActivityManagerSingleton.get();}private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}

AMS通知Laucher组件进入pause状态

ActivityManagerService#startActivity

1.参数caller指向Launcher组件所运行的应用程序进程的Application对象。

2.参数intent包含了即将要启动的MainActivity的组件信息。

3.参数resultTo指向ActivityManagerService内部的一个ActivityRecord对象,它里面保存了Launcher组件的详细信息。

ActivityStarter#startActivityMayWait

1.通过mSupervisor.resolveIntent(intent, resolvedType, userId)获取即将启动Activity组件的更多信息,(PackageManagerServcie解析参数intent的内容)。

2.通过ProcessRecord callerApp = mService.getRecordForAppLocked(caller);

在ActivityManagerService中,每一个应用程序都使用一个ProcessRecord对象来描述,并且保存在ActivityManagerService内部。

3.ActivityStarter类的成员变量mService指向了ActivityManagerService,通过getRecordForAppLocked来获得caller对应的一个ProcessRecord对象callerApp。参数caller指向的是Launcher组件所运行的应用程序进程的一个ApplicationThread对象。

Launcher组件的onPause流程

在handlePauseActivity方法中,会将Message对象msg的成员变量obj转换后的SomeArgs中的arg1强制转换成一个IBinder接口。第一件事就是调用成员函数performUserLeavingActivity向Launcher组件发送一个用户离开事件通知,即调用它的成员函数onUserLeaveHint。第二件事就是调用成员函数performPauseActivity向Launcher组件发送一个中止事件通知,即调用它的成员函数onPause。调用QueuedWork类的静态成员函数waitToFinish等待完成前面的一些数据写入操作,例如,将数据写入磁盘的操作。由于现在Launcher组件即将要进入Paused状态了,因此要保证它前面所有数据写入操作都处理完成;否则等它重新进入Resume状态时,就无法恢复之前保存的数据。最后通过ActivityManagerService给它发送的中止Launcher组件的进程间通信请求。

Launcher组件pause状态到新进程启动:

ActivityStack#activityPausedLocked

在这个方法中会调用函数completePauseLocked来执行启动MainActivity组件的操作。并将这个ActivityRecord对象的成员变量state的值设置为ActivityState.PAUSED,表示Launcher组件已经进入了Pause状态了。

ActivityStackSupervisor#startSpecificActivityLocked

检查与ActivityRecord对象r对应的Actiivty组件所需要的应用程序进程是否已经存在。如果存在直接调用realStartActivityLocked函数来启动Actiivty组件。否则先以这个用户ID和进程名称来创建一个应用程序进程,然后再通知这个应用程序进程将Activity组件启动起来。

在ActivityManagerService中,每一个Activity组件都有一个用户ID和一个进程的名称,其中用户ID是在安装Activity组件时由PackageManagerService分配的,而进程名称则是由该Activity组件的android:process属性来决定的。ActivityManagerService在启动一个Activity组件时,首先会以它用户ID和进程名称来检查系统中是否存在一个对应的应用程序进程。如果存在,则会直接通知这个应用程序将该Activity组件启动起来。否则,就会先以这个用户ID和进程名称来创建一个应用程序进程,然后再通知这个应用程序进程将Activity组件启动起来。

新进程启动

ActivityManagerService#startProcessLocked

该方法中依然会检查请求创建的应用程序是否已经存在了,如果不存在。会根据指定的名称以及用于ID来创建一个ProcessRecordLocked对象,同时将其保存到ActivityManagerService类的成员变量mProcessNames。

ActivityManagerServcie#startProcessLocked

得到要创建的应用程序进程的用户ID和用户组ID。调用Process类的静态成员函数start来启动一个新的应用程序进程新的应用程序进程创建成功之后,当前进程会得到一个大于0的进程ID,保存在ProcessStartResult中。调用Process类的静态成员函数start启动一个新的应用程序时,通过entryPoint指定该进程的入口函数为"android.app.ActivityThread"类的静态成员函数main。

同时向ActivityManagerService所在的线程的消息队列中发送一个类型为PROC_START_TIMEOUT_MSG的消息,并且指定这个消息在PROC_START_TIMEOUT之后处理。新的应用程序进程必须在PROC_START_TIMEOUT毫秒之内完成启动工作,并且向ActivityManagerService发送一个完成的通知,以便ActivityManagerService可以在它里面启动一个Activity组件。否则认为超时,就不能将相应的Activity组件启动起来。

#ActivityThread的main方法到scheduleLauchActivity

新的应用程序在启动时,主要做两件事;

1.在进程中创建一个ActivityThread对象,并且调用它的成员函数attach向ActivityManagerService发送一个启动完成通知。

2.调用Looper类的静态成员函数prepareMainLooper创建一个消息循环,并且在向ActivityManagerService发送启动完成通知之后,使得当前进程进入到这个消息循环中。

主要关注新的应用程序是如何向ActivityManagerService发送一个启动完成通知的。在创建ActivityThread对象thread时,会同时在它内部创建一个ApplicationThread对象mAppThread。前面提到,ActivityThread对象内部的ApplicationThread对象是一个Binder本地对象,ActivityManagerService就是通过它来和应用程序进程通信的。

ActivityManagerService#attachApplicationLocked

参数pid指向了前面所创建是应用程序进程PID,在前面,ActivityManagerService以这个PID为关键字将一个ProcessRecord对象保存在了成员变量mPidsSelfLocked中。通过参数pid将这个ProcessRecord对象取回来,并且保存在变量app中。得到的ProcessRecord对象app就是用来描述新创建的应用程序进程的。初始化ProcessRecord对象app,就是用来描述新创建的应用程序进程的。最重要的就是初始化其thread成员变量,这个IApplicationThread类型的变量,就是ActivityManagerService通过其与新创建的应用程序进行通信的。

ActivityStackSupervisor#attachApplicationLocked

得到位于Activity组件顶端的一个ActivityRecord对象top,它对应的Activity组件就是即将要启动的MainActivity组件。检查这个Activity组价的用户ID和进程名称是否与ProcessRecord对象app所描述的应用程序的用户ID和进程名称一致。如果一致,那么说明ActivityRecord对象top所描述的Activity组件是应该在ProcessRecord对象app所描述的应用程序进程中启动的。

ActivityStackSupervisor#realStartActivityLocked

将该Activity组件添加到参数app所描述的应用程序进程的Activity组件列表中。通知前面创建的应用程序进程启动由参数r所描述的一个Activity组件,即MainActivity。

# 从ActivityThread的scheduleLaunchActivity到Activity的onCreate方法

将Messgae对象msg的成员变量obj转换成一个ActivityClientRecord对象r,接着调用getPackageInfoNoCheck方法获得一个LoadedApk对象,并且保存在ActivityClientRecord对象r的成员变量packageInfo中。

每一个Android应用程序都是打包在一个Apk文件中的。一个Apk文件包含了一个Android应用程序的所有资源,应用程序进程在启动一个Actiivty组件时,需要将它所属的Apk文件加载进来,以便可以访问它里面的资源。在ActivityThread类内部,就使用一个LoadedApk对象来描述一个已经加载的Apk文件。

ActivityThread#handleLaunchActivity

启动由ActivityClientRecord对象r所描述的一个Activity组件。

ActivityThread#performLaunchActivity

创建和初始化一个ContextImpl对象appContext,用来作为所创建的Activity对象activity的运行上下文环境,通过它就可以访问到特定的应用程序资源,以及启动其他的应用程序组件。使用ContextImpl对象appContext和ActiivtyClientRecord对象r来初始化Activity对象activity。最终调用成员变量mInstrumentation的函数callActivityOnCreate将Activity启动起来。

注意:

ActivityClientRecord对象r的成员变量token是一个Ibinder对象,它指向了AcitivityManagerService内部的一个ActivityRecord对象。这个ActivityRecord对象和ActivityClientRecord对象r一样,都是用来描述前面启动的Activity组件的,只不过前者都是在ActivityManagerService中使用,而后者在应用程序中使用。

Android 8.0 Activity启动流程分析相关推荐

  1. Cocos2d-x3.3RC0的Android编译Activity启动流程分析

    http://www.itnose.net/detail/6142692.html 本文将从引擎源码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,下面是详细分析 ...

  2. c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

    在我的上一篇文章: AJie:按下电源键后竟然发生了这一幕 -- Android 系统启动流程分析​zhuanlan.zhihu.com 我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS( ...

  3. Android 10.0 Activity启动详解(二)

    Android 10.0 Activity启动详解(一) 我们在上一篇博客中已经介绍了关于Activity的一些基础概念.这一篇博客我们以Android 10.0的代码来分析Activity的启动流程 ...

  4. Android 13.0 SystemUI 启动流程

    1.手机开机后,Android系统首先会创建一个Zygote(核心进程). 2.由Zygote启动SystemServer. 3.SystemServer会启动系统运行所需的众多核心服务和普通服务.以 ...

  5. Android | Activity 启动流程分析

    前言 Activity 类是 android 应用的关键组件,在日常开发中,绝对少不了组件.既然用了这么久,你知道他的启动流程

  6. Android 源码 PackageManagerService 启动流程分析

    <Android 源码 installPackage 流程分析>一节着重分析了 apk 安装流程,接下来我们分析 PackageManagerService 启动时都做了些什么? 执行 P ...

  7. Android 7.0 WifiMonitor工作流程分析

    2019独角兽企业重金招聘Python工程师标准>>> 在wifi启动扫描的分析过程中,出现了多次WifiMonitor的操作,在此分析一下这个函数是如何工作的. 在Android的 ...

  8. Android 9.0 Vold 挂载流程分析

    在Android 系统中所有的热插拔设备都是通过Vold 进程挂载的.通过kernel–>vold–>StorageManagerService这样的架构去逐级上报热插拔事件. 一.Vol ...

  9. android启动流程之lk,Android系统之LK启动流程分析(一)

    1.前言 LK是Little Kernel的缩写,在Qualcomm平台的Android系统中普遍采用LK作为bootloader,它是一个开源项目,LK是整个系统的引导部分,所以不是独立存在的,但是 ...

最新文章

  1. 网络工程师课程---4、网络层(网关是什么)
  2. javascript面象对象编程的三种方法
  3. 牛客多校4 - Basic Gcd Problem(预处理质因子的个数)
  4. Python学习预备
  5. 静态内部类----Java
  6. C\C++不经意间留下的知识空白------有符号数和无符号数
  7. Super Jumping! Jumping! Jumping! 最长上升子序列+DP
  8. L1-058 6翻了 (15 分)-PAT 团体程序设计天梯赛 GPLT
  9. 灰色按钮激活程序的原理 (学习)
  10. PDF编辑器中文版免费下载哪里可以下载?
  11. class文件反编译成java文件
  12. EpsonL360清零软件+清零方法
  13. html网页简单实现图片轮播效果,CSS3简单实现图片切换轮播
  14. steam无盘服务器,网吧服务器如何安装steam平台和正版游戏?
  15. 二、11【FPGA】时序逻辑电路——计数器
  16. awk OFS问题说明
  17. ctrypto-js中,DES解密的iv向量处理
  18. 基于Spark的新闻推荐系统,包含爬虫项目、web网站以及spark推荐系统
  19. 一周信创舆情观察(6.14~6.20)
  20. CreateWindow创建异形窗口(不规则窗口) - WINDOWS API 第三弹 异形窗口。

热门文章

  1. DOTween的使用(一) DOTween实现代码延时执行 + DOTween.Sequence的(队列)的简单介绍
  2. 数字证书认证(CA)中心
  3. geoserver发布切片影像地图
  4. BSN智能合约开发培训-CITA(三)
  5. 计算机总是无法完成更新失败,Win10系统更新失败无法完成更新正在撤销更改的解决方法...
  6. 共享充电宝再涨价达每小时6元 客服:市场需求决定的
  7. TensorFlow2.0-GPU加速
  8. 华为平板计算机的隐藏功能,华为平板MatePad的3种隐藏玩法,你都不知道呢
  9. 用python画卡通人物的画法_教你绘制扁平化风格的卡通人物肖像
  10. VTK笔记-图形相关-圆锥体-vtkConeSoure类