例如,如果在activity A启动后,再启动activity B,在某个时刻activityA因为系统回收资源的问题要被杀掉,A通过onSaveInstanceState将有机会保存其用户界面状态,使得将来用户返回到activityA时能通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢复界面的状态。
关于onSaveInstanceState(),是在函数里面保存一些View有用的数据到一个Parcelable对象并返回。在Activity的onSaveInstanceState(BundleoutState)中调用View的onSaveInstanceState (),返回Parcelable对象,
当系统调用Activity的的onRestoreInstanceState(BundlesavedInstanceState)时,
这就是onSaveInstanceState()和
如果我们没有覆写onSaveInstanceState()方法,此方法的默认实现会自动保存activity中的某些状态数据,比如activity中各种UI控件的状态.。android应用框架中定义的几乎所有UI控件都恰当的实现了onSaveInstanceState()方法,因此当activity被摧毁和重建时,这些UI控件会自动保存和恢复状态数据.比如EditText控件会自动保存和恢复输入的数据,而CheckBox控件会自动保存和恢复选中状态.开发者只需要为这些控件指定一个唯一的ID(通过设置android:id属性即可),剩余的事情就可以自动完成了.如果没有为控件指定ID, 则这个控件就不会进行自动的数据保存和恢复操作。
由上所述, 如果我们需要覆写onSaveInstanceState()方法,一般会在第一行代码中调用该方法的默认实现:super.onSaveInstanceState(outState)。
5. 是否需要重写onSaveInstanceState()方法
如果需要保存额外的数据时,就需要覆写onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只适合保存瞬态数据,比如UI控件的状态,成员变量的值等,而不应该用来保存持久化数据,持久化数据应该当用户离开当前的activity时,在onPause()中保存(比如将数据保存到数据库或文件中)。说到这里,还要说一点的就是在onPause()中不适合用来保存比较费时的数据,所以这点要理解。
由于onSaveInstanceState()方法方法不一定会被调用, 因此不适合在该方法中保存持久化数据,例如向数据库中插入记录等.保存持久化数据的操作应该放在onPause()中。若是永久性值,则在onPause()中保存;若大量,则另开线程吧,别阻塞UI线程。
除了系统处于内存不足的原因会摧毁activity之外, 某些系统设置的改变也会导致activity的摧毁和重建.例如改变屏幕方向(见上例), 改变设备语言设定, 键盘弹出等。
另外,当屏幕的方向发生了改变,Activity会被摧毁并且被重新创建,如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。可以重写Activity的onSaveInstanceState() 和 onRestoreInstanceState()方法,如下代码所示:
packagecom.code.test;
importandroid.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity{
privateString message = "";
privateEditText text = null;
privateButton button = null;
@Override
public voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (EditText) findViewById(R.id.editText1);
button = (Button)findViewById(R.id.btnSave);
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "保存",Toast.LENGTH_SHORT).show();
}
});
}
@Override
public voidonResume(){
super.onResume();
Toast.makeText(getApplicationContext(), message,Toast.LENGTH_LONG).show();
}
@Override
public voidonSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("message",text.getText().toString());
}
@Override
public voidonRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
message = savedInstanceState.getString("message");
}
}
@Override
public void onSaveInstanceState(BundlesavedInstanceState) {
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
// etc.
super.onSaveInstanceState(savedInstanceState);
}
@Override
public voidonRestoreInstanceState(BundlesavedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
boolean myBoolean=savedInstanceState.getBoolean("MyBoolean");
double myDouble =savedInstanceState.getDouble("myDouble");
}
我们可以用旋转屏幕来测试我们的程序保存状态的能力。因为一般旋转时,activity会被重新执行onCreate()onStart()等操作,程序此时能够保存状态是很重要的。可以考虑使用该方法保存数据。当然了在旋转屏幕时我们除了使用onSaveInstanceState()外,还可以使用onRetainNonConfiguration
@Override
public Object onRetainNonConfigurationInstance() {
// TODO Auto-generated method stub
// 在这里设置需要保存的内容,在切换时不是bundle了,我们可以直接通过object来代替。
return super.onRetainNonConfigurationInstance();
}
在恢复屏幕时可以不使用onRestoreInstanceState(),而使用getLastNonConfigurationI
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取上次切换屏幕保存的对象
Object obj = getLastNonConfigurationInstance();
}
说到这里了,可能有的人就要问了,既然onSaveInstanceState()和onRetainNonConfiguration
之前在其它网站上看到有的朋友说:"
例如下面代码所示要保存一个复杂的数据:
public class DataHolder {
int a;
Bitmap b;
String s;
}
@Override
public Object onRetainNonConfigurationInstance() {
// TODO Auto-generated method stub
DataHolder dh = new DataHolder();
dh.a = a;
dh.b = b;
dh.s = s;
return dh;
}
不过呢,onRetainNonConfiguration
下面是一个使用onRetainNonConfiguration
package com.rotation.demo;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
public class RotationAsyncActivity extends Activity {
private ProgressBar progressBar=null;// 进度条
private RotationAsyncTask asyncTask=null; // 异步任务类
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar=(ProgressBar)findViewById(R.id.progress);
asyncTask=(RotationAsyncTask)getLastNonConfigurationInstance();// 获取对象
if (asyncTask==null) {
asyncTask=new RotationAsyncTask(this);
asyncTask.execute();
}else {
asyncTask.attach(this);
updateProgress(asyncTask.getProgress());
if (asyncTask.getProgress()>=100) {
markAsDone();
}
}
}
@Override
public Object onRetainNonConfigurationInstance() {
asyncTask.detach();
return asyncTask;
}
private void updateProgress(int progress) {
progressBar.setProgress(progress);
}
private void markAsDone() {
findViewById(R.id.completed).setVisibility(View.VISIBLE);
}
// 异步任务类
private static class RotationAsyncTask extends AsyncTask<Void, Void, Void> {
private RotationAsyncActivity activity=null;
private int progress=0;
public RotationAsyncTask() {
// TODO Auto-generated constructor stub
}
public RotationAsyncTask(RotationAsyncActivity activity) {
attach(activity);
}
@Override
protected Void doInBackground(Void... unused) {
for (int i=0;i<20;i++) {
SystemClock.sleep(500);
publishProgress();
}
return null;
}
@Override
protected void onProgressUpdate(Void... unused) {
if (activity==null) {
Log.w("RotationAsyncActivity", "onProgressUpdate()");
}else {
progress += 5;
activity.updateProgress(progress);
}
}
@Override
protected void onPostExecute(Void unused) {
if (activity==null) {
Log.w("RotationAsyncActivity", "onPostExecute()");
}else {
activity.markAsDone();
}
}
protected void detach() {
activity = null;
}
protected void attach(RotationAsyncActivity activity) {
this.activity = activity;
}
protected int getProgress() {
return progress;
}
}
}
我们在运行示例时就会发现,无论怎样旋转屏幕都不会影响进度条的更新与下载,需要解释下的是这里我并没有设置下载功能, 以上就是在Android中关于InstanceState保存数据和恢复数据的过程,在这里我想再重复一遍:onSaveInstanceState()和onRestoreInstanceState()机制来保存数据时,它仅在非用户显式的指令杀死应用程序时保存和恢复数据。我们可以使用它在我们的程序中来保存数据,可以作为保存数据的一种方式,但在使用过程中需要注意其使用原理和方法。
转载地址:
http://blog.csdn.net/hn_tzy/article/details/9495101