目录
Activity 的生命周期:
正常情况下的生命周期:
- onCreate():当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法。通常用于初始化设置,为Activity设置所要使用的布局文件,为按钮绑定监听器等静态的设置操作。
- onStart():当Activity可见未获得用户焦点不能交互时系统会调用。
- onRestart():当Activity已经停止然后重新被启动时系统会调用。
- onResume():当Activity可见且获得用户焦点能交互时系统会调用。
- onPause():用来存储持久数据。到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情。从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。
- onStop():当Activity被新的Activity完全覆盖不可见时被系统调用。
- onDestroy():当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用,(整个生命周期只调用1次)用来释放onCreate()方法中创建的资源,如结束线程等。
当我们从一个旧的Activity中打开一个新的Activity时,旧Activity和新Activity的生命周期:
- 旧Activity调用onPause()
- 新Acticity调用onCreate()
- 新Acticity调用onStart()
- 新Acticity调用onResume()
- 旧Activity调用onStop()
异常情况下Activity的生命周期:
首先学习一下onSaveInstanceState和onRestoreInstanceState方法:
onSaveInstanceState是用来保存UI状态的,你可以使用它保存你所想保存的东西,在Activity杀死之前,它一般在onStop或者onPause之前触发,onRestoreInstanceState则是在onResume之前触发回复状态,至于复写这个方法后onCreate方法是否会被调用。
1.Activity被杀死了,onCreate会被调用,且onRestoreInstanceState 在 onResume之前恢复上次保存的信息。
2.Activity没被杀死,onCreate不会被调用,但onRestoreInstanceState 仍然会被调用,在 onResume之前恢复上次保存的信息。
onSaveInstanceState和onRestoreInstanceState 是一对兄弟,一个负责存储,一个负责取出.“不一定”是成对的被调用的。
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。onSaveInstanceState(Activity被意外销毁时调用)
情况1:资源相关的系统配置发生改变导致Activity被杀死并重新创建
- Activity出现意外情况时
- 调用onSaveInstanceState()保存UI状态
- 调用onDestory()销毁Activity,释放资源
- 当该Activity被重新创建时
- 调用onCreate()创建
- 调用onRestoreInstanceState()恢复UI状态(在onStart前被调用)
接下来有一个问题:
如果某项配置发生改变,我们能不能不重新创建Activity呢?
当然可以。
这里就提到了一个configChanges属性
比如,我们不想让Activity旋转的时候重建,就可以给configChanges属性添加一个orientation值,如下所示:
android:configChanges="orientation"
想多个值,可以用 " | " 连接起来
configChanges属性的其他值:
VALUE | DESCRIPTION |
mcc | 国际移动用户识别码所属国家代号是改变了,sim被侦测到了,去更新mcc MCC是移动用户所属国家代号 |
mnc | 国际移动用户识别码的移动网号码是改变了, sim被侦测到了,去更新mnc MNC是移动网号码,最多由两位数字组成,用于识别移动用户所归属的移动通信网 |
locale | 用户所在区域发生变化,一般是用户切换了语言时,切换后的语言会显示出来 |
touchscreen | 触摸屏是改变了------通常是不会发生的 |
keyboard | 键盘发生了改变----例如用户用了外部的键盘 |
keyboardHidden | 键盘的可用性发生了改变 |
navigation | 导航发生了变化-----通常也不会发生 |
screenLayout | 屏幕的显示发生了变化------不同的显示被激活 |
fontScale | 字体比例发生了变化----选择了不同的全局字体 |
uiMode | 用户的模式发生了变化 |
orientation | 屏幕方向改变了---横竖屏切换 |
screenSize | 屏幕大小改变了 |
smallestScreenSize | 屏幕的物理大小改变了,如:连接到一个外部的屏幕上 |
情况2:资源内存不足导致低优先级的Activity被杀死
- 前台Acticity----------正在和用户交互的Activity,优先级最高
- 可见但非前台Activity)---------可见但无法与用户进行交互(处于onStart状态
- 后台Activity---------已经被暂停的Activity,优先级最低(处于onPause和onStop状态)
后续都会调用onSaveInstanceState和onRestoreInstanceState来存储和恢复数据
Activity的启动模式
standard(标准模式):
系统默认的启动模式,栈结构,先进后出,打开一个activity入栈,再打开下个activity,接着入栈,我们平时直接创建的Activity都是这种模式的Activity这种模式的Activity的特点是:只要你创建了Activity实例,一旦激活该Activity,则会向任务栈中加入新创建的实例,退出Activity则会在任务栈中销毁该实例。
singleTop(栈顶服用模式):
如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例;举个例子:
目前栈内为ABCD,A为栈底,D为栈顶,这时我们启动一个D(D为singleTop模式),栈内情况为ABCD(如果D为standard模式,栈内变为ABCDD)。
singleTask(栈内复用模式):
如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都销毁;singleInstance(单实例模式):
如果我们将某个activity设置成这个singleStance启动模式,则当激活这个activity之后单独放到一个栈,下次再使用的时候,直接使用这个栈,比如打电话应用就是一个singleStance模式启动的activity