ACTIVITY状态保存

  关于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然后我们在此方法中恢复即可。布局文件如下:

View Code
 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代码:

View Code
 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’的信息了

 

posted @ 2013-05-12 11:51  g.hui  阅读(882)  评论(1编辑  收藏  举报