Activity
:作为四大组件之一,也是与用户交互最多的组件,因此为了更好的交互效果,了解Activity的生命周期,正确分配每个阶段该完成的工作就显得十分必要,例如:我们不能在onPause
中做耗时的操作,因为新的Activity必须在前一个Activity
执行了onPause
才能执行onResume
显示。
Activity
的生命周期分为两部分,一部分是典型情况
下的生命周期,另一部分是异常情况
的生命周期。
典型情况
:正常的生命周期,用户参与的情况。
异常情况
:Activity被收回或者设备的Configuration发生变化导致Activity被销毁并重建。
onCreate
和onStart
:这两个阶段Activity正在创建,可以进行初始化动作,比如setContentView,初始化资源。
onResume
:这时Activity已经前台可见,具备交互功能
onPause
:表示Activity正在停止,这是可以做一些存储数据,停止动画的工作,不能太耗时,不然会影响新的Activity的显示。
onStop
:表示Activity即将停止,这里可以做一些重量级的操作,也不能太耗时
onDestroy
:表示Activity即将销毁,这里可以做一些回收动作和资源释放。
我的操作及日志情况
通过上述分析,我们可以清晰的看到生命周期的调用顺序,注意,
1.MainActivity跳到SecondActivity的时候,先是回调MainActivity的onPause,然后才回调SecondActivity的直到onResume的操作,为了SecondActivity尽快切换到前台,不应该在onPause中做太耗时的操作。
2.MainActivity跳到SecondActivity的时候,SecondActivity回调onResume后,调用了MainActivity的onStop,这个方法也不应该有太耗时的操作,不然SecondActivity会有卡顿的情况
当系统配置变化时,Activity会被销毁,但系统会调用onSaveInstanceState
来保存当前的Activity的状态,这个方法在onStop
之前调用,然后调用onRestoreInstateState
来恢复数据,这个方法在onStart
之后调用
MainActivity.java
/** * 注意到onCreate中也有`Bundle savedInstanceState`,也可以在回调onCreate的时候恢复数据,注意先判断savedInstanceState非空 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"MainActivity-->onCreate");
setContentView(R.layout.activity_main);
Log.i("savedInstanceState-->","is null? "+(savedInstanceState==null)+"");
editText = (EditText) findViewById(R.id.edit_text);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.i(TAG,"MainActivity-->onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i(TAG,"MainActivity-->onRestoreInstanceState");
}
通过上述分析,我们可以清晰的看到在切换横竖屏时数据的保存及恢复情况,自己如果有想保存的数据也可以在saveInstanceState中实现,恢复时既可以在onCreate中,也可以在onRestoreInstanceState中,注意,
1.在按下home键,或是切换到另外的Activity时,也会回调onSaveInstanceState保存数据,因为系统也怕在你长时间不操作或内存不足时,Activity被回收,但如果没有发生系统回收,则不会回调onRestoreInstanceState进行数据恢复
2.即便是我们按下home键或者是跳转到另一个Activity在跳转回来之前的Activity仍旧保存着之前的EditText中的状态信息。(Stopped状态下的Activity仍然保存着所有的状态信息和成员变量)
Activity按优先级分三种:
(1)前台Activity:正在和用户交互的Activity,优先级高
(2)可见但非前台Activity:比如有一个AlertDialog弹出时
(3)后台Activity:执行了onStop的Activity
内存不足时,系统就会按照优先级由低到高回收Activity
由上述栗子我们知道资源相关系统配置改变会导致Activity被杀死并重建,不过我们也可以阻止Activity重建,只需给Activity指定configChanges
属性即可。
例如我们上述的旋转屏幕的栗子,可以给Activity指定orientation和screenSize属性,Activity就不会重建。
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(TAG,"MainActivity-->onConfigurationChanged newConfigOrientation"+newConfig.orientation);
}
由上述日志可以看出,当我们配置了configChanges后,不会回调onSaveInstanceState和onRestoreInstanceState,也没有onCreate,取而代之的是onConfigurationChanged,因此我们可以在其中实现自己的逻辑,下面一个小demo在onConfigurationChanged根据横竖屏更改EditText中的内容
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
editText.setText("ORIENTATION_LANDSCAPE");
}else if(newConfig.orientation==Configuration.ORIENTATION_PORTRAIT){
editText.setText("ORIENTATION_PORTRAIT");
}
}
下面为常用的配置引起Activity重建的属性
项目 | 含义 |
---|---|
locale | 切换系统语言 |
keyboardHidden | 键盘的可访问性发生改变,比如用户调出了键盘 |
orientation | 屏幕方向发生改变,旋转手机屏幕 |
screenSize | 屏幕尺寸发生改变,旋转屏幕也会导致屏幕尺寸发生改变,当minSdkVersion和targetSdkVersion均低于13的时候,此选项不会导致Activity重启,否则会导致Activity重启 |