典型情况下的生命周期分析
- activity 第一次启动 :
onCreate
->onStart
->onResume
- 用户打开新activity,原activity的过程 :
onPause
->onStop
.(如果新activity采用透明主题,当前activity不会调用onStop
) - 再次回到原activity :
onRestart
->onStart
->onResume
- 用户按回退键 :
onPause
->onStop
->onDestory
- 屏幕息屏 :
- 屏幕亮屏 :
-
onCreate
,onDestory
表示一个activity的创建和销毁,一次生命周期过程中,只能调用一次. -
onStart
,onStop
是从activity的是否可见 -
onResume
,onPause
是从activity是否位于前台来判断的
新页面启动时,旧Activity 调用
onPause
后,新Activity才调用onResume
.
旧onPause
->新onCreate
->新onStart
->新onResume
->旧onStop
因此,不能在 onPause
中做耗时的操作.
异常情况下生命周期分析
常见的两种情况下,导致Activity重建
- 资源相关的系统配置发生改变导致Activity被杀死后重建
- 资源内存不足导致优先级低的Activity被杀死
异常重建过程中,数据的保存和恢复
Activity被异常终止后,会调用 onSaveInstanceState
方法, 改方法在 onStop
之前调用,使用Bundle
对象来保存数据.正常结束Activity生命周期的过程是不会调用 onSaveInstanceState
方法.
Activity 重建后, 将调用 onRestoreInstanceState
用于恢复数据,销毁时保存的Bundle
数据,将以回调参数的形式返回给onRestoreInstanceState
,和onCreate
方法.
正常启动时, onCreate
中的Bundle
为空,异常重建时不为空.
因此,在 onCreate
中恢复数据,需要判断 Bundle
数据是否为空,而onRestoreInstanceState
只有异常重建时,才会被调用.
官方建议,在onRestoreInstanceState
中恢复数据.
onSaveInstanceState
,onRestoreInstanceState
系统自动恢复某些数据
系统在Activity异常销毁过程中,会为我们保存当前Activity的视图结构,并在重建过程中恢复.
如 文本输入框的 输入数据, 列表滚动的位置, TextView中的选中状态和文本内容
Activity的优先级
- 前台Activity (正在和用户交互的Activity) 优先级最高
- 可见但非前台Activity (如被对话框挡住的Activity)
- 后台Activity (onStop) 优先级最低
当系统内存不足时, 按照上述优先级去杀死目标Activity所在的进程.
配置改变后,不销毁Activity
Android 配置文件中, 可以给Activity指定 configChanges
属性, 不让Activity销毁.
- configChanges含义
值 | 说明 |
---|---|
“mcc” | IMSI 移动国家/地区代码 (MCC) 发生了变化 - 检测到了 SIM 并更新了 MCC。 |
“mnc” | IMSI 移动网络代码 (MNC) 发生了变化 - 检测到了 SIM 并更新了 MNC。 |
“locale” | 语言区域发生了变化 — 用户为文本选择了新的显示语言。 |
“touchscreen” | 触摸屏发生了变化。(这种情况通常永远不会发生。) |
“keyboard” | 键盘类型发生了变化 — 例如,用户插入了一个外置键盘。 |
“keyboardHidden” | 键盘无障碍功能发生了变化 — 例如,用户显示了硬件键盘。 |
“navigation” | 导航类型(轨迹球/方向键)发生了变化。(这种情况通常永远不会发生。) |
“screenLayout” | 屏幕布局发生了变化 — 这可能是由激活了其他显示方式所致。 |
“fontScale” | 字体缩放系数发生了变化 — 用户选择了新的全局字号。 |
“uiMode” | 用户界面模式发生了变化 — 这可能是因用户将设备放入桌面/车载基座或夜间模式发生变化所致。 请参阅 UiModeManager。 此项为 API 级别 8 中新增配置。 |
“orientation” | 屏幕方向发生了变化 — 用户旋转了设备。注:如果您的应用面向 API 级别 13 或更高级别(按照 minSdkVersion 和 targetSdkVersion 属性所声明的级别),则还应声明 "screenSize" 配置,因为当设备在横向与纵向之间切换时,该配置也会发生变化。 |
“screenSize” | 当前可用屏幕尺寸发生了变化。它表示当前可用尺寸相对于当前纵横比的变化,因此会在用户在横向与纵向之间切换时发生变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。此项为 API 级别 13 中新增配置。 |
“smallestScreenSize” | 物理屏幕尺寸发生了变化。它表示与方向无关的尺寸变化,因此只有在实际物理屏幕尺寸发生变化(如切换到外部显示器)时才会变化。 对此配置的变更对应于smallestWidth 配置的变化。 不过,如果您的应用面向 API 级别 12 或更低级别,则 Activity 始终会自行处理此配置变更(即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动 Activity)。此项为 API 级别 13 中新增配置。 |
“layoutDirection” | 布局方向发生了变化。例如,从从左至右 (LTR) 更改为从右至左 (RTL)。 此项为 API 级别 17 中新增配置。 |
如要禁止屏幕翻转,导致Activity销毁,可做如下操作
<activity android:name=".MyActivity"
android:configChanges="orientation|“screenSize”"
android:label="@string/app_name">
如果屏幕发生旋转,Activity不会销毁,但是会回调 onConfigurationChanged
方法.
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}