Android的Activity主要用于展示界面,对于应用来说是用户最直接感知的部件,所以了解它的工作方式对于开发者而言很重要。首先来测试一下单个Activity的生命周期函数调用过程,通常启动一个Activity要经过onCreate->onStart->onResume这三个周期函数。现在写一个简单的测试小程序,每个生命周期函数里只打印这个函数调用的消息。
public class FirstActivity extends AppCompatActivity {
private int count = 10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
Log.d(getTag(), getPageName() + "onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.d(getTag(), getPageName() + "onStart");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(getTag(), getPageName() + "onRestart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(getTag(), getPageName() + "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(getTag(), getPageName() + "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(getTag(), getPageName() + "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(getTag(), getPageName() + "onDestroy");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(getTag(), getPageName() + "onConfigurationChanged");
Log.d(getTag(), getPageName() + " " + newConfig.fontScale);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("key", count);
Log.d(getTag(), getPageName() + "onSaveInstanceState");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
count = savedInstanceState.getInt("key");
Log.d(getTag(), getPageName() + "onRestoreInstanceState");
}
private String getPageName() {
return "FirstActivity-----------";
}
private String getTag() {
return "AndroidTest";
}
public void openSecondActivity(View v) {
count = 5;
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
}
现在启动这个Activity观察一下调用了哪些生命周期函数。
如果用户点击Home键将当前Activity放到后台则会调用onPause->onSaveInstanceState->onStop三个周期函数,点击Home键查看一下调用的结果。
再次将Activity掉到前台,查看调用函数。
可以看到前面进入后台的时候调用了onSaveInstanceState方法,但是从后台重新返回的时候并没有调用onRestoreInstanceState方法。这时因为后台没有销毁该Activity实例,所以就没必要重新恢复数据。现在直接点击底部的回退按钮果然调用了onPause->onStop->onDestroy。可以看到这里onSaveInstanceState并没有被调用,这时因为系统对用户自己销毁Activity的操作不会保留状态,只有当系统资源不足的时候需要回收Activity才会做状态保存操作。
如果想测试onRestoreInstanceState被调用的情况,需要到设置->开发者选项->不保留活动勾选上,这样Activity进入后台以后就会被销毁,重新进入前台就会重新创建。现在勾选上不保留活动,然后将Activity进入后台,查看调用方法。可见进入后台之后系统销毁了Activity,所以调用了onDestroy。
现在再把Activity掉入前台,观察调用函数,可以看到系统确实回调了onRestoreInstanceState方法。
对于onSaveInstanceState方法数据最好在super.onSaveInstanceState之前,因为super.onSaveInstanceState应该会做数据保存的动作。但是实际测试的时候发现在super方法调用之后保存数据一样可以在onRestoreInstanceState方法里获得。本例中保存了一个count参数,它最开始是10,当用户点击一个button之后变成5,然后把Activity进入后台。这时可以看到count在super之后保存到outState里。
当从新Activity返回时onRestoreInstanceState被调用,count的值被成功恢复出来了。
还有一个比较少用的生命周期函数onConfigurationChanged,它通常是在系统的配置改变的时候才会调用,比如屏幕的方向改变了或者字体大小改变了才会调用。常见的就是横竖屏幕切换,如果不做任何配置,系统会销毁当前的Activity再重新创建一个新的Activity。配置横竖屏切换的在设置->显示->设备旋转时,选中旋转屏幕内容方向。查看调用的生命周期函数。
现在配置一下Activity的android:configChanges。再观察系统调用函数可以看到系统调用了onConfigurationChanged,没有重新创建Activity。需要注意的是android3.0之后orientation|screenSize同时设置才能保证onConfigurationChanged被调用。
<activity android:name=".FirstActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
讨论完了单个Activity的生命周期,现在看一下两个Activity的生命周期调用情况。启动第二个Activity,然后观察调用的生命周期函数。可以看到首先调用了FirstActivity.onPause->SecondActivity.onCreate->SecondActivity.onStart->SecondActivity.onResume->FirstActivity.onSaveInstanceState->FirstActivity.onStop。系统会优先展示新启动的Activity,然后才调用FirstActivity进入后台回调。