onSaveInstanceState和onRestoreInstanceState总结
Activity有两个方法,onSaveInstanceState() 和 onRestoreInstanceState(),分别用来保存和恢复activity被杀死之后的状态。
当一个activity被系统杀死之前,onSaveInstanceState()将被调用,用户将有机会保存界面状态信息,将来返回activity的时候可以通过oncreate(bundle)和onRestoreInstanceState(Bundle)恢复原来的状态信息。
2. 触发情景onSaveInstanceState方法通常可以被以下几种情况触发:
1. 当用户启动另外一个activity时,当前activity退居后台
2. 当用户按下home键
3. 关闭屏幕
4. 屏幕横竖屏切换时
5. 切换任务把之前activity遮盖时
onSaveInstanceState()的调用遵循一个重要的原则,就是操作系统未经过用户批准,自行销毁activity时该方法将被调用。如果用户手动调用finish()或者使用返回键结束activity,那么onSaveInstanceState()将不被调用。当activity被销毁时,可以通过调用onRestoreInstanceState()相关状态恢复activity的相关状态。onSaveInstanceState()和onRestoreInstanceState()的调用并不是成对出现的,onRestoreInstanceState()方法调用的时机是当一个activity切实被系统销毁重启时才触发。
onSaveInstanceState()默认会自动保存activity某些状态数据,比如activity控件的各种状态,当一个activity被销毁和启动的时候,这些控件的基本状态将会得到保存。需要注意的是,我们需要为这些需要默认保存数据的控件设置唯一的Id,之后状态将会得到保存。onSaveInstanceState()方法里只适合用于保存瞬态数据,而不适合用来保存持久化数据,因为onSaveInstanceState()并不是activity的生命周期方法,调用时机具有不确定性,而保存持久化数据应该放在activity生命周期的确定行为中进行。
3.测试下面是基于onSaveInstanceState()和onRestoreInstanceState()的测试,新建一个activity,重写所有的activity生命周期方法,onSaveInstanceState()和onRestoreInstanceState()方法。以下测试结果使用三星GT-N5100进行测试所得,其他类型设备没有具体测试。
1. 启动activity,然后按home键,测试结果如下:
2. 直接启动另外一个activity,原来的activity退居后台
3. 按下电源键锁屏
5. 切换任务把之前activity遮盖时
6. 如果当前activity没有全部被遮盖,相当于启动了另外一个非全屏的activity。
可以发现,这种情况下onSaveInstanceState()仍然会被调用,只不过当前activity没有触发onStop方法。
这里需要注意,复写onSaveInstanceState()和onRestoreInstanceState()方法时需要调用父类的方法,否则默认状态比如说edittext输入的信息将得不到保存,同时必须注意给控件赋予唯一的Id。
onSaveInstanceState()方法调用后,之后activity启动时onCreate()的传入参数不为空,可以通过获取某些信息对原来的状态进行还原。
4.总结:1. onSaveInstanceState()和onRestoreInstanceState()是实现activity在非用户主观结束时系统提供给用户保存当前activity被杀死后状态的一种方法。
2. onSaveInstanceState()和onRestoreInstanceState()的调用并不是成对出现的,只有Activity已经被销毁了,onRestoreInstanceState()才被调用。
3. onSaveInstanceState()和onRestoreInstanceState()并不是activity的生命周期方法,所以并不一定会回调,只能保持一些特定的临时数据,需要保存持久化数据必须在生命周期方法中实现。
4. onSaveInstanceState()只有在当activity有非用户主观被销毁时才调用,如果是用户主观结束当前activity则不会调用。
5. onSaveInstanceState()的调用一般发生在onStop之前onPause之后(虽然很多资料说在onPause之前,但是我测试的结果没有这种情况),onRestoreInstanceState()的调用发生在onStart之后,onResume之前。
5.测试代码启动一个对话框式样的activity需要在AndroidManifest.xml里对应的activity里增加如下代码:
android:theme="@android:style/Theme.Dialog"
测试代码如下:
public class TestActivity1 extends Activity {
private EditText edtvTest = null;
private Button btnTest = null;
private String info = "";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test1);
if(savedInstanceState != null) {
System.out.println("-----------------> text: " + savedInstanceState.getString("text"));
}
System.out.println("-----------------> onCreate");
edtvTest = (EditText) findViewById(R.id.edtv_test);
btnTest = (Button) findViewById(R.id.btn_test);
btnTest.setOnClickListener(listener);
Toast.makeText(getApplicationContext(), info, Toast.LENGTH_LONG).show();
}
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.btn_test:
Intent it1 = new Intent();
it1.setClass(TestActivity1.this, TestActivity2.class);
startActivity(it1);
break;
default:
break;
}
}
};
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
System.out.println("-----------------> onStart");
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
System.out.println("-----------------> onRestart");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("-----------------> onResume");
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
System.out.println("-----------------> onPause");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
System.out.println("-----------------> onStop");
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
System.out.println("-----------------> onDestroy");
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("text", edtvTest.getText().toString());
System.out.println("-----------------> onSaveInstanceState");
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
info = savedInstanceState.getString("text");
System.out.println("-----------------> onRestoreInstanceState");
}
}