Activity的生命周期
一.生命周期分类
1.典型生命周期:
在有用户参与的情况下,正常完整的生命周期
2.异常生命周期:
(1).系统内存不足,Activity被系统回收
(2).当前设备的Configuration改变,导致Activity销毁重建
二.典型情况下的生命周期
1.onCreate
2.onRestart
用户行为导致Activity从不可见到可见,会被调用
3.onStart
可见,不可交互
4.onResume
可见,可交互
5.onPause
不可太耗时,执行完成后,才会执行新开启Activity的onResume
6.onStop
可做轻微重量级回收,不可太耗时
7.onDestory
三.典型情况下生命周期的补充说明
现有两个Activity,分别为A和B
1.首次启动A
onCreate -> onStart -> onResume
2.启动B或者按下home键
onPause -> onStop(若B透明,则不走此方法)
3.再次回到A
onRestart -> onStart -> onResume
4.按bask键回退(销毁)
onPause -> onStop -> onDestory
5.由A开启B,A的onPause和B的onResume执行顺序
(A)onPause -> (B)onCreate,onStart,onResume -> (A)onStop
故不能在A的onPause中执行耗时操作,尽量放于onStop
6.整个生命周期中,方法的成对分析
(1).onCreate和onDestory
标识Activity的创建和销毁,只能调用一次
(2).onStart和onStop
标识Activity是否可见,随着用户的操作或者设备屏幕的点亮或熄灭,可能会被调用多次
(3).onResume和onPause
标识Activity是否在前台(是否可交互),随着用户的操作或者设备屏幕的点亮或熄灭,可能会被调用多次
四.异常情况下生命周期补充说明
1.系统内存不足,导致低优先级的Activity被杀死
(1).Activity按照优先级的分类
前台Activity,正在和用户交互,最高
可见但非前台Activity,比如Activity中弹出一个对话框,次之
后台Activity,已被暂停的Activity,比如执行了onStop,最低
(2).当系统内存不足时,则会按照优先级从低到高杀死Activity所在进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来恢复数据
(3).若一个进行中没有四大组件在运行,则该进程很快将被杀死,若一些后台工作不适合脱离四大组件而独自运行在后台中,可将该后台工作放入Service中从而保证进程有一定优先级,不会轻易被系统杀死
2.资源相关的系统配置发生改变导致Activity被杀死并重新创建
(1).默认情况下,若Activity不做特殊处理,当系统配置发生改变,Activity就会被杀死并重建
(2).其onPause,onStop,onDestory会被调用
(3).由于Activity在异常情况下被终止并且有可能重新显示的情况下,系统会调用onSaveInstanceState来保存当前Activity的状态,onSaveInstanceState一定会在onStop之前调用,可能会在onPause之前或之后,正常情况下,系统不会调用onSaveInstanceState
(4).Activity被重建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate,故可通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建,并可取出之前保存的参数并恢复,onRestoreInstanceState在onStart之后被调用
(5).Activity重建后,调用onRestoreInstanceState和onCreate的区别
onRestoreInstanceState一旦被调用,其参数Bundle savedInstanceState一定是有值的,不需要额外判空,官方推荐此方法来恢复数据
onCreate被调用可能是正常启动,也可能是异常下启动,故其参数Bundle savedInstanceState可能为null,需要判空
(6).保存和恢复View的层次结构,系统的工作流程
首先,Activity被意外终止,Activity会调用onSaveInstanceState来保存数据
然后Activity会委托Window来保存数据
接着Window再委托它上面的顶层容器来保存数据,该顶层容器是一个ViewGroup,一般来说是DecorView
最后,顶层容器再去一一通知它的子元素来保存数据
五.系统配置发生改变后,如何避免Activity的重新创建
1.常见的configChanges属性
keyboard 键盘类型发生改变,比如使用了外接键盘
keyboardHidden 键盘的可访问性发生改变,比如调出了键盘
orientation 屏幕方向发生改变,比如旋转手机屏幕
screenSize 屏幕尺寸发生改变,比如旋转手机屏幕,API > 13时,才会导致Activity重启
2.可以给Activity在清单文件中指定configChanges属性
android:configChanges="orientation|screenSize"
此后Activity不会被重建,也不会调用onSaveInstanceState和onRestoreInstanceState来保存和恢复数据,而是调用onConfigurationChanged方法
Activity的启动模式
一.启动模式的4种类型
1.standard 标准模式
(1).每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在
(2).标准模式下,被启动的Activity位于启动Activity的任务栈中,比如A启动B(标准模式),则B进入到A所在的栈中
2.singleTop 栈顶复用模式
(1).若新Activity位于栈顶,那此Activity不会重建,但onNewIntent方法会被调用,此时该Activity的onCreate,onStart不会被调用
(2).若新Activity实例已存在但不是位于栈顶,则该Activity会重建
(3).假设目前栈内Activity为ABCD,再次开启D:
若D为standard,则为ABCDD;
若D为singleTop,则为ABCD
3.singleTask 栈内复用模式
(1).若Activity在栈中已存在,多次启动该Activity,都不会重新创建实例,但onNewIntent方法会被调用
(2).什么是Activity所需的任务栈?
a.和一个参数TaskAffinity有关,可翻译为任务相关性,该参数标识了一个Activity所需要的任务栈的名字
b.默认情况下,所有Activity所需要的任务栈的名字为应用的包名
c.可以为每个Activity都单独指定TaskAffinity属性,该属性值必须不能和包名相同,否则相当于没有指定
d.可在清单文件中指出,则Activity会运行在这个名字即com.xiaozai.cn的任务栈中
android:TaskAffinity="com.xiaozai.cn"
f. TaskAffinity属性主要和singleTask启动模式配合使用,其他情况下没有意义
(3).开启singleTask模式Activity A的流程梳理:
(4).举例说明
a.当前任务栈为S1,内有ABC三个Activity,D为singleTask,且所需任务栈为S2,由于S2和D的实例均不存在,故先创建任务栈S2,再创建D的实例,并压入S2中
b.当前任务栈为S1,内有ABC三个Activity,D为singleTask,且且所需任务栈为S1,由于S1已存在,故会创建D的实例,并将其压入S1中
c.当前任务栈为S1,内有ADBC四个Activity,D为singleTask,且且所需任务栈为S1,由于S1已存在,根据栈内复用原则,此时不会重建D的实例,而是把D调到栈顶,并把D上面的BC清除出栈,同时回调onNewIntent方法,最终栈S1中为AD
4.singleInstance 单一实例模式
除了具备singleTask模式所有的特性外,还加强一点,就是singleInstance模式的Activity,只能单独的位于一个任务栈中,若A为singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个任务栈被系统销毁了
二.如何为Activity指定启动模式?
1.分类
(1).通过AndroidMenifest为Activity指定启动模式
android:launchMode="singleTask"
(2).通过在Intent中设置标志位为Activity指定启动模式
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
2.区别
(1).优先级
第二种优先级高于第一种,二者同时存在,以第二种为准
(2).限定范围
第一种无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识
第二种无法为Activity指定singleInstance模式
三.Activity的Flags
1.FLAG_ACTIVITY_NEW_TASK
为Activity指定singleTask启动模式,和在清单文件中指定效果一样
2.FLAG_ACTIVITY_SINGLE_TOP
为Activity指定singleTop启动模式,和在清单文件中指定效果一样
3.FLAG_ACTIVITY_CLEAR_TOP
具有此标记的Activity,当前启动时,在同一个任务栈中所有位于它上面的Activity都要出栈.
此模式一般需要和FLAG_ACTIVITY_NEW_TASK配合使用