概述
Activity是一个程序组件,为用户提供一个可交互的画面。
每一个Activity都会被分配一个窗口(根DecorView),此窗口通常是浮在其他窗口上的
一、Activity 的生命周期
Activity 的生命周期分为两个部分,一部分是典型情况下的生命周期,另一种是异常情况下的生命周期,比如因为设备的配置信息变化、Activity被系统回收等非正常情况下的生命周期
1.1 典型情况下的生命周期分析
1. 正常情况下,Activity经历的生命周期:
onCreate() :创建,可以做初始化操作
onStart() :可见不可交互
onResume() :可见可交互
onPause() :可见可交互,可以做一些操作,但不可以太耗时
onStop() :可见不可交互,可以做一些操作,但不可以太耗时
onDestroy() :销毁
onRestart() :表示Activity正在重新启动。由可见不可交互 - 可见可交互
生命周期图
2. 常用几种情况的执行的生命周期
-
启动一个特定的Activity,第一次启动,执行的生命周期如下:
onCreate() -> onStart() -> onResume()
-
back回退/activity.finish() , 执行的生命周期如下:
onPause() -> onStop() -> onDestroy()
-
在Activity A中启动Activity B,A的执行的生命周期如下:
onPause() -> onStop()
-
在Activity A中启动Activity B后又回到Activity A时(相当于Activity从不可见不可交互状态切换到可见可交互状态下、从桌面回到APP热启动)
onRestart() -> onStart() -> onResume()
-
在Activity A中启动Activity B,A、B的执行的生命周期如下:
A - onPause() B - onCreate() B - onStart() B - onResume() A - onStop()
-
在Activity A中启动Activity B(B是透明的),A、B的执行的生命周期如下:
A - onPause() B - onCreate() B - onStart() B - onResume()
-
在Activity A中启动Activity B后又回到Activity A,A、B的生命周期执行
B - onPause() A - onRestart() A - onStart() A - onResume() B - onStop() B - onDestroy()
-
在Activity A中启动Activity B(B透明的)后又回到Activity A,A、B的生命周期执行
B - onPause() A - onResume() B - onStop() B - onDestroy()
-
在Activity A中启动Activity B,B是透明主题/对话框,A的执行的生命周期如下:
onPause()
-
用户按Home键Activity执行的生命周期如下:
onPause() -> onStop()
总结如下:
从整个生命周期来说,onCreate和 onDestroy是配对的,分别标识着 Activity的创建和销毁,并且只可能有一次调用。
从Activity是否可见来说, onStart和 onStop是配对的,这两个方法可能被调用多次;
从Activity是否可交互来说, onResume和 onPause是配对的,这两个方法可能被调用多次。
3. 思考:在 Activity A中开启Activity B ,那么B的 onCreate和A的onPause哪个先执行呢?
答案是:A的onPause先执行,再执行B的onCreate()
1.2 异常情况下的生命周期分析
情况1 :资源相关的系统配置改变导致的Activity被销毁和重建
默认情况下,当系统配置发生变化后,Activity就会被销毁和重建。
onSaveInstanceState()只会是系统在Activity被销毁且有机会重建的情况下才调用的。
Activity销毁:会调用onSaveInstanceState()来保存当前Activity的状态。
在onStop()方法之前,与onPause()无一定的顺序关系。
Activity重建:会调用onRestoreInstanceState()来获取Activity销毁前保存的数据。
onRestoreInstanceState()在onStart()执行之后数据通过Bundle传递。
以上生命周期如下图所示:
异常情况下生命周期图
那么Activity数据是如何保存的呢?保存哪些数据呢?
查看源码
那么如何可以使Activity不被重建呢?
答案:在AndroidManifest.xml中给Activity配置configChanges属性,代码如下
android:configChanges="orientation"
如果需要给configChanges指定多个值时,可以使用“|”连接多个值。
思考:那么设置configChanges后,当屏幕旋转时Activity的生命周期是什么呢?
A - onPause()
A - onSaveInstanceState()
A - onStop()
A - onDestroy()
A - onCreate()
A - onStart()
A - onRestoreInstanceState()
A - onResume()
情况2:资源内存不足导致低优先级的Activity被销毁
- Activity按照优先级从高到低可以分为如下三种
(1)前台 Activity :正在和用户交互的 Activity,优先级最高
(2)可见不可交互的 Activity :比如 Activity中弹出了一个对话框,导致 Activity可见不可交互
(3)后台 Activity :已经被暂停的 Activity,比如执行了 onStop,优先级最低。
当系统内存不足时,系统就会按照上述优先级去杀死目标 Activity所在的进程,并在后续通过 on Savelnstance State和 on Restoreinstance State来存储和恢复数数据。 - 如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此,一些后台工作不适合脱离四大组件而独自运行在后合中,这样进程很容易被杀死,比较好的方法是将后台工作放入 Service中从而保证进程有一定的优先级,这样就不会轻易地被系统杀死。
拓展:
下表是configChanges的值及其含义,仅仅作为了解(常用的是前三个)
项目 | 含义 |
---|---|
orientation | 屏幕方向发生了改变,这个是最常用的,比如旋转了手机屏幕 |
locale | 设备的本地位置发生了改变,一般指切换了系统语言 |
keyboardhidden | 键盘的可访问性发生了改变,比如用户调出了键盘 |
mcc | SM卡唯一标识IMSI(国际移动用户识别码)中的国家代码,由三位数字组成,中国为标识mcc代码发生了改变 |
mnc | SM卡唯一标识IMSI(国际移动用户识别码)中的运营商代码,由两位数字组成,中国移动TD系统为00 、中国联通为01、中国电信为03。此项标识mnc发生改变 |
touchscreen | 触摸屏发生了改变,这个很费解,正常情况下无法发生,可以忽略它 |
keyboard | 键盘类型发生了改变,比如用户使用了外插键盘 |
navigation | 系统导航方式发生了改变,比如采用了轨迹球导航,这个有点费解,很难发生,可以忽略它 |
screenlayout | 屏幕布局发生了改变,很可能是用户激活了另外一个显示设备 |
fontscale | 系统字体缩放比例发生了改变,比如用户选择了一个新字号 |
uiMode | 用户界面模式发生了改变,比如是否开启了夜间模式(API8新添加) |
screensize | 当屏幕的尺寸信息发生了改变,当旋转设备屏幕时,屏幕尺寸会发生变化,这个选项比较特殊,它和编译选项有关,当编译选项中的 min Sdk version和 targetsdk version均低于13时,此选项不会导致Activity重启,否则会导致 Activity重启(API13新添加) |
smallestScreenSize | 设备的物理屏幕尺寸发生改变,这个项目和屏幕的方向没关系,仅仅表示在实际的物理屏幕的尺寸改变的时候发生比如用户切换到了外部的显示设备,这个和screensize一样,当编译选项中的 min Sdk version和 targetsdk version均低于13时,此选项不会导致Activity重启,否则会导致 Activity重启(API13新添加) |
layoutDirection | 当布局方向发生变化,这个属性用的比较少,正常情况下无需修改布局的layoutDirection属性(API17新添加) |
参考:
《Android开发艺术探索》
网友评论