前言

系列文章:

Android Activity 与View 的互动思考
Android Activity 生命周期详解及监听
Android onSaveInstanceState/onRestoreInstanceState 原来要这么理解
Android Fragment 要你何用?
Android Activity/View/Window/Dialog/Fragment 深层次关联(白话解析)

当你编写第一个Android “Hello World” 时,已经不知不觉地与Activity生命周期打交道。这部分是是Android 最基础的知识之一,也是面试的常客,同时也是理解Jetpack 组件的基础。
网上关于此的文章数不胜数,但大部分只流于表象,没有系统性分析,看过之后容易忘却。本系列将会着重分析由此衍生的一系列知识点。
通过本篇文章,你将了解到:

1、什么是生命周期?
2、谁是生命周期的幕后黑手?
3、如何感知生命周期

1、什么是生命周期

这个名字并不是计算机独创的术语,任何有生命的东西都有周期,从出生到死亡,以人为例:

这是一个人的成长轨迹,也是一个人的生命周期,在不同的年龄段表现各异。
俗话说:人活一世,草木一秋。
佛家说的轮回,当一个人入土为安,假设有轮回,在下一个轮回里再经历出生到死亡,这个人还是上一世的那个人吗?
同样的草木凋谢了,在春天再长出来时,还是曾经的它吗?
不是,它们都是新的生命。

Activity 的生命周期

先来看官方经典图:

Activity 作为对象,它是有"生命的",类似人和草木,它的存活周期就是它的生命周期。

为什么生命周期要分不同的阶段?
就像人一样:

1、当处在婴儿阶段,自己每天喝喝奶,没事就哭闹一下,大人就会安抚你。
2、当处在学生时代,就认真做题,大家把你当小孩看待,不用你出门赚钱,景点都能给你学生票五折优惠。
3、当处在工作时代,就好好搬砖,老板会给你福报。
4、…

同样的,对于Activity 来说,在不同的阶段自己内部所做的事情不同,外部监听到Activity的处在不同阶段将会采取不同的措施。
总结来说:

生命周期分阶段既是为了"生命体内部"流转的需要,也是为了让外部知道"生命体"当前所处的阶段进而做出相应的决策。

与人、草木一样,当Activity 经历了一个生命周期后,再次重建时已经不是当初的对象了。

Activity 生命周期不同阶段

主要分为:

可以看出Create 对应 Destroy,Start对应Stop,Resume对应Pause。
既然每个阶段都有回调,那么只需要重写对应的回调方法,添加打印即可测试不同的操作后Activity处在哪个阶段。

接下来看看Activity 常见的切换场景:

Activity A 启动Activity B


图上数字表示发生的顺序,具有时间上的先后顺序。

从Activity A 按Home回到桌面

回到桌面或者最近任务列表:

Activity B 按back 键/调用finish

此时Activity B处在栈顶位置,而Activity A 位于它之下。

Pause 阶段

上面列出的场景都是onPause–>onStop,那么Activity 是否存在只停留在onPause的阶段?
Pause阶段是Activity 可见,但是没有焦点因此无法和用户交互。
可见意味着它的上面有Activity,并且上面的Activity 是透明的,才可以看见底下的Activity。
此种情况下,底下的Activity 处在Pause阶段。

如上图,红色区块是新启动的Activity,该Activity 没有全屏并且透明,可以看到底下Activity 内容,此时它处在Pause阶段。

2、谁是生命周期的幕后黑手?

我们知道Android 是事件驱动的,通过Loop来循环执行MessageQueue里的Message。
问题来了:onCreate、onStart、onStop 是在同一个Message里执行的吗?
要弄清楚这个问题,需要知道回调这些方法的堆栈。众所周知,四大组件都是由AMS(Activity Manager Service)控制的,而AMS 运行在system_server 进程,与咱们的App是不同的进程,AMS 通过Binder 与各个App进行通信。

不清楚的可移步:Android 四大组件通信核心
接下来探究AMS 如何控制Activity 生命周期回调的。

onCreate 调用堆栈

在onCreate()里打个断点,调用栈如下:

可以看出入口是在ActivityThread.java 类里。

1、App进程启动的时,将ApplicationThread 传递给AMS,类似向AMS 注册回调。
2、AMS 通过ApplicationThread 通知App Activity 的生命周期。
3、App 切换到主线程执行对应的方法,最终会执行Activity 的onCreate()、onStart()、onResume()等方法。

其它阶段的调用栈

与onCreate 类似,onStart、onResume、onPause、onStop、onDestroy 阶段同样经历了AMS—>App—>切换到主线程—>回调对应方法。
为方便起见,省去AMS 过程,用图表示如下:

由以上分析可知:

1、Activity 生命周期的幕后黑手是AMS。
2、各个阶段的调用栈很相似,只是变了方法名而已。
3、onCreate、onStart、onStop 不是在同一个Message里执行的,但是都是在主线程执行。

3、如何感知生命周期

注册监听

知道了生命周期的来龙去脉,要监听生命周期就变得非常简单了,只需要在Activity 里重写对应阶段的回调方法即可,这也是我们最基础的选择。
现在有个需求:监听App处在前台还是后台?
Activity 处在后台,那么此时阶段为Stop,回到前台那么此时处会经历Start阶段,在进入Start 阶段时记录+1,在进入Stop阶段时记录-1。若最终结果记录=1,说明App在前台。
这么看来,我们需要一个公共的Activity来进行统一记录,每个新建的Activity 都继承自它,这么做虽然能满足需求,但也有弊端:一是工作量大,二是也不灵活。
实际上还有更好的方式来全局监听各个Activity 生命周期。

#Application.javapublic void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {synchronized (mActivityLifecycleCallbacks) {mActivityLifecycleCallbacks.add(callback);}}

Application.java 里有个方法,顾名思义用来注册Activity 生命周期回调的,这个callback 会加入到回调List:mActivityLifecycleCallbacks 里。
先看看ActivityLifecycleCallbacks 的构成:

它是个接口,乍一看有很多方法,实际上都是有规律可循的,总结下来就是监听了:

Create、Start、Resume、Pause、Stop、Destroy、SaveInstanceState

各个阶段的回调。
而每个阶段分为三个小阶段:

此阶段之前、阶段中、此阶段之后

如对于Create阶段,定义了三个回调方法:

#Application.javapublic interface ActivityLifecycleCallbacks {//Create阶段之前default void onActivityPreCreated(@android.annotation.NonNull Activity activity,@android.annotation.Nullable Bundle savedInstanceState) {}//Create阶段当中void onActivityCreated(@android.annotation.NonNull Activity activity, @android.annotation.Nullable Bundle savedInstanceState);//Create阶段之后default void onActivityPostCreated(@android.annotation.NonNull Activity activity,@android.annotation.Nullable Bundle savedInstanceState) {}//...}

而只有处在当前阶段的方法必须要实现类实现,其它两个方法都是默认的(default 修饰)。

生命周期回调原理

注册了监听后,来分析一下该回调是如何被调用的。
既然是监听Activity 生命周期,那么应当从Activity.java 里入手。
记得咱们之前分析的Activity 回调方法调用栈,还是以onCreate为例:

#Activity.javaprotected void onCreate(@android.annotation.Nullable Bundle savedInstanceState) {...mFragments.dispatchCreate();//分发dispatchActivityCreated(savedInstanceState);...}private void dispatchActivityCreated(@android.annotation.Nullable Bundle savedInstanceState) {//调用Application里的方法getApplication().dispatchActivityCreated(this, savedInstanceState);}

而在Application.java里的实现为:

#Application.javavoid dispatchActivityCreated(@android.annotation.NonNull Activity activity,@android.annotation.Nullable Bundle savedInstanceState) {//收集注册列表,即是将mActivityLifecycleCallbacks(List),转为数组Object[] callbacks = collectActivityLifecycleCallbacks();if (callbacks != null) {for (int i=0; i<callbacks.length; i++) {//调用对应的回调方法((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,savedInstanceState);}}}

虽然以上只是分析了onCreate,然而其他方法也是同样的套路,大同小异。

1、每当Activity 处在不同的阶段时,会检测Application里是否有监听它(Activity)的生命周期,若是则告知监听者当前所处的阶段。
2、若是重写了Activity 对应的方法,并添加了打印,那么Application里的回调方法先执行才会执行到Activity里的打印,因为它是在Activity父类里执行的。

以上即是Activity 生命周期的梳理,下篇将会分析onSaveInstanceState/onRestoreInstanceState 原理以及应用场景,并引入Jetpack ViewModel与之对比。

透明Activity/生命周期监听 demo 请查看:github合集

本文基于Android 10.0

您若喜欢,请点赞、关注,您的鼓励是我前进的动力

持续更新中,和我一起步步为营系统、深入学习Android

1、Android各种Context的前世今生
2、Android DecorView 必知必会
3、Window/WindowManager 不可不知之事
4、View Measure/Layout/Draw 真明白了
5、Android事件分发全套服务
6、Android invalidate/postInvalidate/requestLayout 彻底厘清
7、Android Window 如何确定大小/onMeasure()多次执行原因
8、Android事件驱动Handler-Message-Looper解析
9、Android 键盘一招搞定
10、Android 各种坐标彻底明了
11、Android Activity/Window/View 的background
12、Android Activity创建到View的显示过
13、Android IPC 系列
14、Android 存储系列
15、Java 并发系列不再疑惑
16、Java 线程池系列
17、Android Jetpack 前置基础系列
18、Android Jetpack 易学易懂系列

Android Activity 生命周期详解及监听相关推荐

  1. xamarin Android activity生命周期详解

    学Xamarin我为什么要写这样一篇关于Android 的activity生命周期的文章 已经学Xamarin android有一段时间了,现在想起当初Xamarin也走了不少的弯路.当然Xamari ...

  2. Android面试之Activity生命周期详解

    Activity生命周期详解 一 Activity的四种状态: Activity的生命周期中存在四种基本的状态:活动状态(Active/Runing),暂停状态(Paused),停止状态(Stoppe ...

  3. Activity生命周期详解及最佳实践

    前言 该文章来自一个开源项目,致力于翻译Google官方文档,很棒,已经有成果了.PDF版本可以去这里下载http://hukai.me/eBooks/AndroidTrainingCHS.pdf,以 ...

  4. Activity生命周期详解

    在我的Android四大组件详解一文中已经对Activity的生命周期进行过一个比较详细的介绍.这篇文章我们再来更加深入地介绍Activity的生命周期. 一.Activity的生命周期方法如下: o ...

  5. Fragment的懒加载与生命周期详解

    提示:本文仅为笔者学习记录 Fragment的懒加载与生命周期详解 什么是懒加载 了解Fragment的生命周期 onAttach onCreate onCreateView onActivityCr ...

  6. Fragment生命周期详解

    关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Frag ...

  7. vue 声明周期函数_Vue 生命周期详解

    Vue 生命周期详解 Vue 生命周期流程 最开始,用户使用 new Vue() 创建根 Vue 实例,或者 Vue 实例化子组件都会调用_init方法(我们将这两种实例都称为vm): functio ...

  8. taro生命周期详解

    taro生命周期详解 taro介绍 生命周期 react的钩子函数 为兼容小程序的钩子函数 个别生命周期详解以及注意 1.render()函数 2.constructor()构造函数 3.在各个生命周 ...

  9. 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记

    01.软件项目管理与敏捷方法--敏捷项目生命周期详解笔记 00.与其说是船还不如说是熟练的航行技术保证了成功的航行.--George William Curtis 01.敏捷项目是一个按照敏捷宣言宗旨 ...

最新文章

  1. iOS架构-分离静态库.a文件并导出.m伪代码文件(11)
  2. JAVA常见面试题之Error、RuntimeException、CheCkedException
  3. NHibernate初学者指南(2):一个完整的例子
  4. 【NLP】相当全面:各种深度学习模型在文本分类任务上的应用
  5. 前端学习(3196):虚拟dom和真实dom
  6. java导出excel文件名_怎么解决java导出excel时文件名乱码
  7. Java学习笔记12——JVM入门
  8. mysql 全文本检索的列_Mysql 全文本检索
  9. keepass2Android密码,Keepass2Android密码管理(快速解锁密码)
  10. 面试:一文搞懂Java集合
  11. Linux驱动下的platform总线架构(转)
  12. 查看Android 系统发送的广播
  13. string.Format字符串格式化说明
  14. python colorbar刻度_matplotlib画3D图修改X,Y,Z,colorbar的刻度值
  15. 台电 平板电脑 html,颜值与功能兼备 台电X6 Pro二合一平板评测
  16. 网络框架分析-全是套路
  17. 解决微信插件wxparse图片大小不能改变的问题
  18. python图书库存管理系统_基于Odoo的物流库存管理系统的设计(Python)
  19. sql左连接查询,去重复数据
  20. 过期系统激活 win7

热门文章

  1. 5月开始,考研重要时间节点要牢记!
  2. 系统和系统实例-软件方法(下)第9章分析类图案例篇Part07
  3. SSH Config 允许使用root密码登陆 PermitRootLogin
  4. Web Apps来袭
  5. gdi+设置图像的透明度
  6. linux应用编程之文件属性
  7. io.jsonwebtoken.UnsupportedJwtException: Signed Claims JWSs are not supported.
  8. 如何判断对象可被GC回收?
  9. 女程序员晒出11月的工资条:工资是高,但是真累,说老十岁一点也不过分
  10. 小米PK华为,智能家居这场战争谁能笑到最后