关于activity的状态保存,以前从来没想过还会有这个问题。这里小小总结一下,以备日后查看。
系统默认实现了哪些
1》可以做个测试,我们可以写个demo,界面上有一个EditText。然后你在里面随便填入一些数据。然后按home键回到桌面,这个时候会调用activity的onPause->onStop,然后我们长按home键选择刚才的demo重新打开发现EditText里面的数据并没有丢失。这是因为执行onStop后此activity并没有并销毁,所以它的各种状态也会被保持。
2》我们接着测试,我们在EditText中填入数据,接着旋转屏幕这个时候会重启activity(系统会先回调onDestory,然后立即回调onCreate)。下面就要分两种情况了:a.如果我们为此EditText在布局文件中设置的有id,这种情况我们会看到此EditText中的数据会被保持 b.若我们没有为此EditText设置id的话,我们会看到旋转屏幕后此EditText里面的内容为空(丢失了)。
那么为什么为EditText中设置了id的话它的数据会被保存呢?
Activity中有一个回调方法:protected void onSaveInstanceState(Bundle outState),此方法会默认保存activiy中所有有id的view的信息。比如CheckBox的是否选中的状态等等。保存下来的这些信息会在Activity的另一个回调方法 protected void onRestoreInstanceState(Bundle savedInstanceState) 中恢复.
总结:
1>只要activity没有被销毁(系统没有回调onDestory),那么它的各种状态就不会丢失。2>若activity由于某种原因(比如旋转屏幕、系统内存紧张)被销毁,则它里面的有id的view的状态将被保存下来。
以上是系统默认实现好的。
需要我们自己实现的
有时候有些信息要我们自己实现保存,防止activity被销毁后信息丢失。比如游戏的进度。假设这样一个场景:我们正在完游戏,然后来了一电话,则游戏将进入后台,又由于手机配置较低或其它的原因,系统杀死了游戏进程。当我们接完电话后,重新回到游戏会发现游戏进度丢失。为了防止这种情况发生,我们应该这样做:
复写Activity的onSaveInstanceState(Bundle outState)及onRestoreInstanceState(Bundle savedInstanceState)方法,将要保存的信息通过onSaveInstanceState方法的Bundle(关于Bundle这里不多做解释)参数保存。然后在onRestoreInstanceState方法中通过它的Bundle参数savedInstanceState进行恢复即可。完整流程请看下图:
通过测试可知:onSaveInstanceState一般会在onPause后被回调,onRestoreInstanceState一般会在onResume前被回调
实例
写个小例子:如上图,其中我们为EditText及button设置的有id而没有为checkBox设置id.在button上,每点击一次增加一次点击次数,我们通过一个全局变量保存点击次数,然后再通过onSaveInstanceState方法的Bundle保存下来,当重新回到Activity时此Bundle会被传给onRestoreInstanceState然后我们在此方法中恢复即可。布局文件如下:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical"
6 tools:context=".ActivityLifeDemo" >
7
8 <EditText
9 android:id="@+id/finish"
10 android:layout_width="fill_parent"
11 android:layout_height="wrap_content" />
12
13 <CheckBox
14 android:layout_width="fill_parent"
15 android:layout_height="wrap_content"
16 android:text="checkBox" />
17
18 <Button
19 android:id="@+id/clickTimes"
20 android:layout_width="fill_parent"
21 android:layout_height="wrap_content"
22 android:text="你点击了0次" />
23
24 </LinearLayout>
Activity代码:
1 public class ActivityLifeDemo extends Activity {
2
3 private static final String TAG = "ActivityLifeDemo";
4
5 private int click_time = 0;
6 Button btn;
7
8 @Override
9 protected void onCreate(Bundle savedInstanceState) {
10 super.onCreate(savedInstanceState);
11 Log.d(TAG, "onCreate");
12 setContentView(R.layout.activity_activity_life_demo);
13 btn = (Button) findViewById(R.id.clickTimes);
14
15 btn.setOnClickListener(new OnClickListener() {
16
17 @Override
18 public void onClick(View v) {
19 btn.setText("你点击了" + ++click_time + "次");
20 }
21 });
22
23 }
24
25 @Override
26 protected void onRestoreInstanceState(Bundle savedInstanceState) {
27 super.onRestoreInstanceState(savedInstanceState);
28 Log.e(TAG, "onRestoreInstanceState");
29 click_time = savedInstanceState.getInt("clickTimes");
30 btn.setText("你点击了" + click_time + "次");
31 }
32
33 @Override
34 protected void onSaveInstanceState(Bundle outState) {
35 super.onSaveInstanceState(outState);
36 Log.e(TAG, "onSaveInstanceState");
37 outState.putInt("clickTimes", click_time);
38 }
39
40 @Override
41 protected void onStart() {
42 super.onStart();
43 Log.d(TAG, "onStart");
44 }
45
46 @Override
47 protected void onRestart() {
48 Log.d(TAG, "onRestart");
49 super.onRestart();
50 }
51
52 @Override
53 protected void onResume() {
54 Log.d(TAG, "onResume");
55 super.onResume();
56 }
57
58 @Override
59 protected void onPause() {
60 Log.d(TAG, "onPause");
61 super.onPause();
62 }
63
64 @Override
65 protected void onStop() {
66 Log.d(TAG, "onStop");
67 super.onStop();
68 }
69
70 @Override
71 protected void onDestroy() {
72 Log.d(TAG, "onDestroy");
73 super.onDestroy();
74 }
75
76 }
如何测试:
在EditText中随便输入一些数据,然后选中Checkbox,再点击几次button。然后旋转屏幕。观察哪些数据丢失哪些数据没变。
结论:会看到Checkbox的信息会丢失,这是因为我们没有为它设置id,EditText的数据不变,button中的点击次数也被保存下来了
需要注意的地方:
1》恢复操作也可以在onCreate(它也有一个Bundle参数)中进行,不过还是建议大家在onRestoreInstanceState中进行,这样各个方法的职责更单一
2》onSaveInstanceState不保证一定会被调用,比如我们点击back键主动关闭activity则系统不会回调onSaveInstanceState方法,此时系统理解我们主动关闭所以不需要保存其状态。因此,对于一些需要持久保存的信息,比如保存到数据库中的不应该写在此方法中写,一般会在onPause中做这些。
3》当我们覆写onSaveInstanceState及onRestoreInstanceState时不应该删除父类的默认实现,否则就不能实现保存‘有id的view’的信息了