前言
Activity
生命周期讲解
正文
一. 概述
本文将分析和总结各种情况下, Activity
的生命周期情况, 包括正常情况下, 异常情况下(如: 用户屏幕旋转, 资源分配不足等)以及特殊情况下(如: 当Activity
上覆盖对话框或者透明Activity
, 当按下Home
键回到桌面时, 当屏幕熄灭时)Activity
生命周期的调用情况; 同时还将简述各个方法下适于做什么工作等
二. 正常情况
2.1 单独的Activity分析
如下为一张典型的Activity
生命周期图(摘自官方文档); 也是正常情况下, 一个Activity
的经历
记忆的时候可以通过两两配对来记
下面将结合上图讲解各个状态:
-
onCreate()
: 一个Activity
启动时只调用一次, 表示Activity
创建; 可以进行一些数据绑定, 类变量初始化或者上一次UI
恢复等工作(通过savedInstanceState
实现) -
onStart()
: 可见, 处于后台, 不能交互 -
onResume()
: 可见, 处于前台 -
onPause()
: 时间短暂, 处于后台; 如果在onPause
的时候再快速的回到当前Activity
, 那么onResume
会被调用(一般用户操作很难实现这一场景); 在Android7.0
或者更高, 应用可以在多窗口模式下运行, 但是只要每个时刻只有一个应用可以得到焦点, 那么此时就需要暂停另一个应用(处于onPause()
状态); (一个处于onPause状态的Activity可能仍然是完全可见的, 比如说在多窗口模式下); 不应该在onPause()
执行数据保存工作, 因为该阶段非常短暂, 同时只有onPause()
执行完, 新Activity
的onResume()
才会执行 -
onStop()
: 不可见, 可以执行一些稍微重量级的工作, 比如资源释放与数据保存 -
onDestroy()
: 表示Activity
销毁, 可以做一些最终的回收工作和资源释放 -
onRestart()
: 表示当当前Activity
从不可见重新变为可见状态时调用
2.2 Activity启动新Activity分析
这里以Activity A正常启动Activity B的情况分析
当A
启动B
的时候, 会依次执行A.onPause()
–> B.onCreate()
–> B.onStart()
–> B.onResume()
–> A.onStop()
可以看出, 只有当A
的onPause()
方法执行完成之后, B
的一系列方法才会调用; 这也说明了onPause()
方法中不能执行耗时操作, 因为新Activity
的onResume()
是在其之后执行的, 如果onPause()
中执行太耗时的操作的话, 会影响新Activity
的显示; 我们应当尽量在onStop()
中操作, 使新Activity
尽快显示出来并出现在前台
三. 异常情况
3.1 资源相关系统配置改变导致Activity被杀死并重新创建
默认情况下, 如果不做特殊处理, 当系统配置发生改变之后, Activity
就会被杀死并重建; 比如: 当手机进行横竖屏切换的时候, Activity
默认就会被销毁重建
在这种情况下, Activity
会依次调用onPause
–> onSaveInstanceState
–> onStop
–> onDestroy
–> onCreate
–> onStart
–> onRestoreInstanceState
–> onResume
需要注意的是这里和正常情况下不同的是, 需要等到Activity
销毁之后才能开始重新创建; 另一个就是, 在Activity
销毁的时候, 会调用onSaveInstanceState
来保存当前Activity
的状态, 该方法的调用在onStop
之前, 但是和onPause
没有既定的时序关系; 但是onRestoreInstanceState
的调用确是在onStart
之后, 有既定的时序关系;
当Activity
销毁重建保存数据的方法是: 委托下级子元素调用其自己的onSaveInstanceState
来保存自己的状态和数据; 即让其关联Window
保存数据, Window
再委托子View
进行数据保存, 最终会调用每个子View
的View.onSaveInstanceState()
来保存自己的数据
当进行数据恢复的时候, onCreate
中的Bundle savedInstanceState
参数不为null
, 可以在此处进行数据恢复, 但是推荐在onRestoreInstanceState
中进行数据恢复
3.2 资源内存不足导致低优先级Activity被杀死
Activity
优先级:
- 前台
Activity
: 正在和用户交互的Activity
, 优先级最高- 可见但非前台
Activity
: 比如Activity
中弹出了一个对话框, 导致Activity
可见但是位于后台, 无法与用户直接交互- 后台
Activity
: 已经被暂停的Activity
, 比如执行了onStop
, 优先级最低
Activity
被杀死的可能性如下:
四. 特殊情况
4.1 按下Home键或者当屏幕熄灭
这种情况下会调用onPause
–> onSaveInstanceState
–> onStop
; 需要注意的是这里仍然调用了onSaveInstanceState
; 但是该情况下是不会调用onRestoreInstanceState
, 原因下面说明
关于onSaveInstanceState
和onRestoreInstanceState
调用的几点说明:
-
onSaveInstanceState
的调用:onSaveInstanceState
会在当Activity
有可能被销毁的时候调用, 用于进行数据保存; 注意, 只要是Activity
有可能被销毁都会调用方法; 比如: 按下Home
键或者屏幕熄灭Activity
进行后台的时候, 该Activity
可能被回收, 所以此时会调用onSaveInstanceState
-
onRestoreInstanceState
的调用和onSaveInstanceState
的调用不一定是成对的,onRestoreInstanceState
要调用的前提是当前Activity
确实被系统销毁了
4.2 透明对话框或者透明Activity
-
当在
Activity
上覆盖一层透明对话框的时候, 不会使Activity
进入后台(不会调用任何方法), 但是Activity
不可和当前用户交互 -
当当前
Activity
启动一个透明Activity
的时候, 会调用前一个Activity
的onPause
, 但是不会调用前一个Activity
的onStop
, 此时前一个Activity
可见但是处于后台
五. 补充
- 考虑
Activity A
跳转到B
的情况: 如果A
跳转到B
(使用startActivityForResult()
),A
被回收的之后再初始化, 此时从B
返回, 那么A
的onActivityResult()
是否还会调用: 参考博客; 结果如下:
在跳转后前一个页面被回收的情况下, 再回到前一个页面,
onActivityResult
依然会被调用, 而且是在onCreate
和onRestoreInstanceState
两个状态恢复结点之后调用, 所以只要做好状态的保存和恢复工作, 就不用担心在onActivityResult
回调时 因相关数据丢失而造成的异常了
- 单纯的使用
startActivityForResult()
的生命周期经历情况是:- B onPause
- A onActivityResult
- A onRestart
- A onStart
- A onResume
- B onStop
- B onDestroy
A
启动B
,B
返回到A
, 经历:- A onPause (—-> A启动B)
- B onCreate
- B onStart
- B onResuem
- A onStop
- B onPause(—–> B返回A)
- A onRestart
- A onStart
- A onResume
- B onStop
- B onDestroy
六. 注
验证代码参见: Github