onRestart()->onStart()->onResume()

b) 完成了第一步对activity生命周期的响应之后,在第二步这里主要是处理窗口的添加动作:把DecorView添加到WindowManager中。完成第二步操作之后,activity的内容便显示到了屏幕上。这个窗口的添加动作属于窗口管理中的一个步骤,具体可参考《Android窗口管理剖析》一文。

以下是部分主要接口到生命周期的响应的内部调用流程图

二、ActivityManagerService及其内部调度流程

\1. 数据结构分析

和窗口管理系统一样,所有的客户端activity在ActivityManagerService(简称AMS)内部都会有一个对应的ActivityRecord,对activity的管理也就是对Activit 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 yRecord的管理。

AMS的相关代码在framework/base/services/java/com/android/server/am,主要的数据结构有:

ActivityManagerService

ActivityStack

ActivityRecord

TaskRecord

ProcessRecord

  1. ActivityManagerService是android框架服务,主要负责处理对android四大组件的管理和响应Client端的请求。此外还包括进程的产生和对WindowManagerService的操作。

  2. ActivityStack是专门实现对ActivityRecord的堆栈式管理而分离出来的一个模块。在Android2.2以前,对ActivityRecord的管理和调度都在ActivityManagerService实现。从android2.3以后,为了实现更好的解耦把对ActivityRecord的管理单独分离出来了,所有对ActivityRecord的调度操作都在ActivityStack里进行。其实Android里所谓的“Activity堆栈”,并不是真正的一个堆栈结构,而是一个ArrayList列表,在这个列表里记录了所有的ActivityRecord,ActivityStack所做的事情就是保证列表的第一个ActivityRecord(也就是“栈顶”)处于运行状态,并且排在列表后面的ActivityRecord的运行状态受到“栈顶”ActivityRecord的影响。

  3. ActivityRecord代表了一个Client端的Activity,记录了Activity的各种属性和管理状态。其中有介个关键的成员变量:

IApplicationToken.StubappToken

appToken作为此ActivityRecord的唯一标识,贯穿了AMS、Activity和WMS。

TaskRecordtask

task标识了此ActivityRecord所属的Task。在ActivityStack对ActivityRecord的位置调整中,更多的是以TaskRecord为单位进行的。如moveTaskToFront()、moveTaskToBack()等接口,会同时移动属于同一个Task的所有activity。 TaskRecord和ActivityRecord是一对多的关系,多个ActivityRecord可能指向同一个TaskRecord

ProcessRecordapp

app标识了Client端的Activity所在的进程。同样的,ProcessRecord和ActivityRecord是一对多的关系,多个ActivityRecord可能指向同一个ProcessRecord。通过访问ProcessRecord中的IApplicationThread可以直接操作Client端的ActivityThread。

  1. TaskRecord记录了task的id、名称等属性。

我们知道,Activity的管理是以Task为单位来进行的,多个行为类似的Activity会被归类到同一个Task中。一般来说,一个apk中的所有Activity都是属于同一个Task,并且Task以apk的包名来命名。但开发者可以在AndroidManifset.xml中通过android:taskAffinity属性给每个Activity配置不同的Task。而什么时候会新开一个Task,新开Task的名字等由ActivityStack里面的逻辑来判断,具体取决于AndroidManifest.xml中的配置和调用startActivity()时传递的flag。

  1. ProcessRecord记录了进程id、进程名字和各种用于调节优先级的状态。还包含了所有运行在该进程的Activity、Service、Receiver、Provider等组件。IApplicationThread thread记录了该进程中的主线程。当一个Acitivity第一次启动时,会首先调用Process.start(“android.app.ActivityThread”)来创建一个新进程并且生成一个ProcessRecord对象。当进程运行起来之后,该进程的主线程会调用Client端的ActivityThread.main()函数,在main()函数中完成Looper的prepare(),并且生成ActivityThread对象,接着在ActivityThread.attach()中调用IActivityManager.attachApplication()回到AMS,在AMS中完成ProcessRecord和IApplicationThread对象的绑定。接下来的流程就会把新Activity和ProcessRecord绑定。

关于ActivityManagerService、ActivityStack、ActivityRecord、TaskRecord、ProcessRecord的关系可用下图表示:

\2. ActivityStack内部调度流程

在整个调度流程中,ActivityStack记录了列表中每个ActivityRecord的当前状态,包括这9个状态:INITIALIZING, RESUMED, PAUSING, PAUSED, STOPPING, STOPPED,FINISHING, DESTROYING, DESTROYED。每个ActivityRecord在任何时刻都处于这9个状态中的其中一个。除此以外,ActivityStack还有几个变量用于辅助调度过程的:

ActivityRecord mResumedActivity

ActivityRecord mPausingActivity

boolean finishing

boolean stopped

ArrayListmStoppingActivities

mResumedActivity指向当前系统中的“栈顶”Activity,当“栈顶”Activity将要被暂停时,mResumedActivity为空,mPausingActivity指向该被暂停的Activity,直到Client端Activity响应onPause()之后回调AMS,mPausingActivity置空。finishing和stopped是ActivityRecord的两个boolean变量,finishing为true表示该Activity将要被销毁;stopped为true表示该Activity处于stopped状态(该stopped变量和Activity的STOPPED状态有重复的嫌疑,可认为是同等的)。

ActivityStack内部的调度围绕着这9个状态来进行,下面通过例子来分析其调度流程。

从Launcher(A)打开新应用(B)

  1. 在Clien端请求打开新Activity之后,ActivityStack首先创建一个ActivityRecord并将其置于“栈顶”,此时ActivityRecord处于INITIALIZING状态。

  2. 接着调用resumeTopActivityLocked()。在resumeTopActivityLocked()中检查mResumedActivity是否为空,此时mResumedActivity指向A,所以肯定不为空。

  3. 调用startPausingLocked()暂停A。此时将mResumedActivity置空,mPausingActivity指向A, 并且将A的状态置为PAUSING。接着调用Activity A的Client端的schedulePauseActivity()将其暂停。

  4. Client端的Activity 响应onPause()并且回调AMS的activityPaused()方法,将A的ActivityRecord的状态置为PAUSED,并把A添加到mStoppingActivities中。完成了A的暂停处理之后,会重新回到第2)步。在第二步中,此时mResumedActivity为空,接下来的流程会最终调用到Activity B 的Client端的scheduleLaunchActivity()。此时Activity B的状态变为RESUMED。

  5. ActivityB的Client端完成Activity的new和初始化并且响应onCreate()->onStart()->onResume(),然后回调AMS的activityIdle()方法告诉AMS已经运行完毕处于空闲状态。

  6. activityIdleLocked()主要是完成经过“堆栈”经过调整之后的“善后”工作。如根据finishing状态完成挂起的销毁操作,处理mStoppingActivities中的挂起stop操作。经过第4)步,A已经在mStoppingActivities中,所以接下来会调用A的Client端的scheduleStopActivity(booleanvisible),在Client端,根据接口参数visible判断,如果visible为false则响应onStop(),否则不响应。在ActivityStack中,visible的值是通过从上到下的计算得出的。如果“栈顶”Activity为fullscreen,则处于“栈顶”底下的其他activity的visible全为false。这个计算过程在第4)步中会执行一次或多次。在执行stop操作时,Activity A的状态从PAUSED变成STOPPING,再变成STOPPED。

在第4)步的处理中,会继续调用resumeTopActivityLocked(),在resumeTopActivityLocked()中,会判断ActivityRecord中的ProcessRecord app是否为空,这里有两种情况:

a) app不为空。

这种情况的前提是,Activity B并不是新打开的而是在一直在后台,并且其进程没有由于内存回收而杀掉。在这种情况下,会直接调用scheduleResumeActivity(),Client端会进行响应:onRestart()->onStart()->onResume()

b) app为空

app为空有三种情况,第一种是ActivityB之前一直在后台运行,由于内存不足被杀掉;第二种是Activity B是新打开的,并且不存在对应的进程;第三中情况是,Activity B 是新打开的,但是其进程仍在运行中。在第一、二种情况中,AMS会启动新进程,并完成Activity B和新进程的ProcessRecord的绑定。

在这三种情况中,最后都会调用scheduleLaunchActivity(),Client端会进响应:onCreate->onStart()->onResume()。

所以,从Launcher(A)打开新Activity (B)的生命周期响应流程如下:

A->onPause()

B->onCreate()

B->onStart()

B->onResume()

A->onStop() (如B不为fullscreen则不响应此方法)

整个调度流程可用下图表示:

Activity管理(三)相关推荐

  1. Activity管理(三):activity内核管理方案详细讲解

    一.Activity的生命周期 Activity的管理同样是基于C/S架构的,所有的activity管理都在server端进行.在Server端对每个activity进行调度的同时,Client端负责 ...

  2. 重拾Activity(三)Activity知识

    这篇文章是从安卓开发者文档找到的Activity资料进行整理的(篇幅较长,用于个人回顾) 目录 这篇文章是从安卓开发者文档找到的Activity资料进行整理的(篇幅较长,用于个人回顾) Activit ...

  3. 【Android工具类】Activity管理工具类AppManager

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 import java.util.Stack;import android.app.Activity; im ...

  4. 用于Activity管理和应用程序退出

    ;import android.app.Activity; import android.content.Context;import java.util.Stack;/*** 应用程序Activit ...

  5. android 应用程序Activity管理类

    import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityMana ...

  6. SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (三) 鉴权

    项目Github地址: https://github.com/baiye21/ShiroDemo SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (一) 简介与配置 S ...

  7. 关于联想“管理三要素”的思考

    联想管理三要素:建班子,定战略,带队伍. 和的三句话:出主意,用干部,抓重点. 出主意-->定战略 用干部-->建班子 抓重点-->带队伍 几乎如出一辙,或许可以成为异曲同工? 不过 ...

  8. android Activity管理器

    android Activity管理器 应用场景 管理活动的Activity,可实现将一个activity添加到管理器.得到保存在管理器中的Activity对象.返回管理器的Activity是否为空. ...

  9. 目标、泳道、时序管理三步法(附合译看板)

    目标.泳道.时序管理三步法: 第一步:确立目标 确定关注的领域,及在各个领域达到的目标. 第二步:将目标分配到泳道 将目标映射到泳道,这样就以一种结构化和有序化的方式思考,拓展了大脑的统筹能力.目标泳 ...

  10. 柳传志经典语录:管理三要素,即建班子、定战略和带队伍

    https://www.toutiao.com/a6639562880482017799/ 2019-01-06 14:07:29 柳传志,中国著名企业家,投资家,曾任联想控股有限公司董事长.联想集团 ...

最新文章

  1. 实例入手Vue-Route给引用组件传值以及实现组件重用
  2. Linux内核源码树建立加载hello模块
  3. php ajax搜索,PHP 与AJAX
  4. linux c read函数返回值,Linuxc - GNU Readline 库及编程简介
  5. RDS For SQL Server链接服务器
  6. SD-WAN三大部署方式 用户现身说法谈优劣势
  7. 《越狱》完结 米帅迷应小心纹身网站挂马
  8. .NET反编译工具Reflector及插件Reflector.FileDisassembler.dll
  9. 学计算机辐射,离散数学对计算机专业系统知识辐射作用.doc
  10. 面试必考:秒杀系统的9个核心知识点,一次性打包给你
  11. qt qtableview 刷新列表_qt qtableview基本用法
  12. Authorization loop detected on Conduit with realm “WSMAN“
  13. Vue3中watch和watchEffect监听的用法
  14. 老挑毛u盘一键装系统计算机意外地,揭谜一键Ghost的“恶”事 大白菜、老毛桃、通用都不干净...
  15. 查看路由器地址是否是公网ip
  16. Unable to access jar file xxx.jar
  17. Serializable的含义
  18. 天啊!中国第一奇人:天天枸杞水,活到256岁!
  19. Android Skeleton使用和阴影动画的说明
  20. 生成带大写英文字母和数字的验证码(手机或邮箱)

热门文章

  1. Linux之awk命令详解
  2. 00911无效字符oracle,ORA-00911: 无效字符 解决
  3. Java——异常处理(详解)
  4. CentOS 7 网络配置(NAT模式)
  5. PHP 循环取2个时间之内的年月
  6. spring定时任务 时间配置cron表达式
  7. 被口臭折磨到不敢张嘴!恋人嫌弃、朋友疏远、同事讨厌,还有救吗?
  8. Cad二次开发绘图1
  9. idea 刷新 项目 中新增的 文件
  10. Chatgpt-3 使用的提取数据集技术、数据集自动化处理和保证数据质量