Android Activity 生命周期详解及监听
前言
系列文章:
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 生命周期详解及监听相关推荐
- xamarin Android activity生命周期详解
学Xamarin我为什么要写这样一篇关于Android 的activity生命周期的文章 已经学Xamarin android有一段时间了,现在想起当初Xamarin也走了不少的弯路.当然Xamari ...
- Android面试之Activity生命周期详解
Activity生命周期详解 一 Activity的四种状态: Activity的生命周期中存在四种基本的状态:活动状态(Active/Runing),暂停状态(Paused),停止状态(Stoppe ...
- Activity生命周期详解及最佳实践
前言 该文章来自一个开源项目,致力于翻译Google官方文档,很棒,已经有成果了.PDF版本可以去这里下载http://hukai.me/eBooks/AndroidTrainingCHS.pdf,以 ...
- Activity生命周期详解
在我的Android四大组件详解一文中已经对Activity的生命周期进行过一个比较详细的介绍.这篇文章我们再来更加深入地介绍Activity的生命周期. 一.Activity的生命周期方法如下: o ...
- Fragment的懒加载与生命周期详解
提示:本文仅为笔者学习记录 Fragment的懒加载与生命周期详解 什么是懒加载 了解Fragment的生命周期 onAttach onCreate onCreateView onActivityCr ...
- Fragment生命周期详解
关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Frag ...
- vue 声明周期函数_Vue 生命周期详解
Vue 生命周期详解 Vue 生命周期流程 最开始,用户使用 new Vue() 创建根 Vue 实例,或者 Vue 实例化子组件都会调用_init方法(我们将这两种实例都称为vm): functio ...
- taro生命周期详解
taro生命周期详解 taro介绍 生命周期 react的钩子函数 为兼容小程序的钩子函数 个别生命周期详解以及注意 1.render()函数 2.constructor()构造函数 3.在各个生命周 ...
- 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记
01.软件项目管理与敏捷方法--敏捷项目生命周期详解笔记 00.与其说是船还不如说是熟练的航行技术保证了成功的航行.--George William Curtis 01.敏捷项目是一个按照敏捷宣言宗旨 ...
最新文章
- iOS架构-分离静态库.a文件并导出.m伪代码文件(11)
- JAVA常见面试题之Error、RuntimeException、CheCkedException
- NHibernate初学者指南(2):一个完整的例子
- 【NLP】相当全面:各种深度学习模型在文本分类任务上的应用
- 前端学习(3196):虚拟dom和真实dom
- java导出excel文件名_怎么解决java导出excel时文件名乱码
- Java学习笔记12——JVM入门
- mysql 全文本检索的列_Mysql 全文本检索
- keepass2Android密码,Keepass2Android密码管理(快速解锁密码)
- 面试:一文搞懂Java集合
- Linux驱动下的platform总线架构(转)
- 查看Android 系统发送的广播
- string.Format字符串格式化说明
- python colorbar刻度_matplotlib画3D图修改X,Y,Z,colorbar的刻度值
- 台电 平板电脑 html,颜值与功能兼备 台电X6 Pro二合一平板评测
- 网络框架分析-全是套路
- 解决微信插件wxparse图片大小不能改变的问题
- python图书库存管理系统_基于Odoo的物流库存管理系统的设计(Python)
- sql左连接查询,去重复数据
- 过期系统激活 win7
热门文章
- 5月开始,考研重要时间节点要牢记!
- 系统和系统实例-软件方法(下)第9章分析类图案例篇Part07
- SSH Config 允许使用root密码登陆 PermitRootLogin
- Web Apps来袭
- gdi+设置图像的透明度
- linux应用编程之文件属性
- io.jsonwebtoken.UnsupportedJwtException: Signed Claims JWSs are not supported.
- 如何判断对象可被GC回收?
- 女程序员晒出11月的工资条:工资是高,但是真累,说老十岁一点也不过分
- 小米PK华为,智能家居这场战争谁能笑到最后