Android 学习笔记之实时保存数据-现场保护onSaveInstanceState()

时间:2023-01-21 04:26:41
数据保存:在软件开发中我们希望保存下各个Activity数据,以实现客户数据的时时保存,达到较好的用户体验。
那么我们需要解决如下问题:
1.什么时候保存?
2.保存哪些数据?
    我想保存应用产生的数据,而这些用户的数据是在Activity与用户进行交互的时候产生的,就是界面上的数据,或者状态。
3.如何进行保存?
4.保存到哪里?
5.编写合适的例子?
创造思路,去哪寻找答案,首先,我想保存应用产生的数据,而这些用户的数据是在Activity与用户进行交互的时候产生的,所以我们进入Activity进行查找。
Activity源码:
 * <ul>
* <li> {@link #onCreate} is where you initialize your activity. Most
* importantly, here you will usually call {@link #setContentView(int)}
* with a layout resource defining your UI, and using {@link #findViewById}
* to retrieve the widgets in that UI that you need to interact with
* programmatically.

onCreate是初始化你的Activity,在这里你可以调用setContentView(int)与layout资源来定义你的UI界面。使用findViewById来取出您交互的控件

 * <li> {@link #onPause} is where you deal with the user leaving your
* activity. Most importantly, any changes made by the user should at this
* point be committed (usually to the
* {@link android.content.ContentProvider} holding the data).
* </ul>

这句的意思是说,onPause是处理用户离开时的方法。最重要的,任何用户操作产生的数据应该在这里进行提交,使用android.content.ContentProvider}来保存数据。

到此我们可以得出结论:
1.什么时候保存?
  一、在onPause时进行保存操作
3.如何进行保存?
使用ContentProvider类进行处理。
怎么处理?继续读
到此,我们要回来看看android.content.ContentProvider
我们进入ContentProvider,但是是用来处理共享数据的,所以我们的结论不是最好的方式。
{@link android.app.Activity#onPause} to commit changes to data and
 * otherwise prepare to stop interacting with the user.
继续向下读,
Because of this, you should use the onPause method to write any persistent data (such as user edits) to storage. In addition, the method onSaveInstanceState(Bundle) is called before placing the activity in such a background state, allowing you to save away any dynamic instance state in your activity into the given Bundle, to be later received in onCreate if the activity needs to be re-created. See the Process Lifecycle section for more information on how the lifecycle of a process is tied to the activities it is hosting. Note that it is important to save persistent data in onPause instead of onSaveInstanceState because the later is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.

我们可以使用onSaveInstanceState(Bundle)方法进行存储,然后onRestoreInstanceState 处进行处理,即拿到值。

如何使用onSaveInstanceState(Bundle)方法?
我们在layout中加一个文本框和button
 Android 学习笔记之实时保存数据-现场保护onSaveInstanceState()
Android 学习笔记之实时保存数据-现场保护onSaveInstanceState()
重写onSaveInstanceState方法,
// 将数据保存到savedInstanceState对象中, 该对象会在重建activity时传递给onCreate方法
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
} @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}

这种方式可以在旋转的时候进行数据保存,但是使用Actionbar向上跳不行,原因是:

* <p>Do not confuse this method with activity lifecycle callbacks such as
* {@link #onPause}, which is always called when an activity is being placed
* in the background or on its way to destruction, or {@link #onStop} which
* is called before destruction. One example of when {@link #onPause} and
* {@link #onStop} is called and not this method is when a user navigates back
* from activity B to activity A: there is no need to call {@link #onSaveInstanceState}
* on B because that particular instance will never be restored, so the
* system avoids calling it. An example when {@link #onPause} is called and
* not {@link #onSaveInstanceState} is when activity B is launched in front of activity A:
* the system may avoid calling {@link #onSaveInstanceState} on activity A if it isn't
* killed during the lifetime of B since the state of the user interface of
* A will stay intact.

  不要将这个方法和activity生命周期回调如onPause()或onStop()搞混淆了,onPause()在activtiy被放置到背景或者自行销毁时总会被调用,onStop()在activity被销毁时被调用。一个会调用onPause()和onStop(),但不触发onSaveInstanceState的例子是当用户从activity B返回到activity A时:没有必要调用B的onSaveInstanceState(Bundle),此时的B实例永远不会被恢复,因此系统会避免调用它。一个调用onPause()但不调用onSaveInstanceState的例子是当activity B启动并处在activity A的前端:如果在B的整个生命周期里A的用户界面状态都没有被破坏的话,系统是不会调用activity A的onSaveInstanceState(Bundle)的。(http://blog.csdn.net/ddna/article/details/5123482)

所以这种方式不能永久保存数据,适合瞬时保存数据。
什么时候调用onSaveInstanceState方法。(亲测)http://www.cnblogs.com/hanyonglu/archive/2012/03/28/2420515.html

(1)、当用户按下HOME键时。

  这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,因此系统会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则

  (2)、长按HOME键,选择运行其他的程序时。

  (3)、按下电源按键(关闭屏幕显示)时。

  (4)、从activity A中启动一个新的activity时。

  (5)、屏幕方向切换时,例如从竖屏切换到横屏时。

  在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState()一定会被执行,且也一定会执行onRestoreInstanceState()。

特别说明

如果我们没覆写onSaveInstanceState()方法,此方法会默认自动保存Activity中的某些数据,比如UI控件的状态和值,前提是需要指定控件一个唯一的ID,否则控件的数据不会出现保存。

那么什么时候保存覆写这个方法?

 如果需要保存额外的数据时, 就需要覆写onSaveInstanceState()方法。大家需要注意的是:onSaveInstanceState()方法只适合保存瞬态数据, 比如UI控件的状态, 成员变量的值等,而不应该用来保存持久化数据,持久化数据应该当用户离开当前的 activity时,在 onPause() 中保存(比如将数据保存到数据库或文件中)。说到这里,还要说一点的就是在onPause()中不适合用来保存比较费时的数据,所以这点要理解。

至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行

到此我们解决我们的问题:

4.保存到哪里?
瞬时的,使用系统提供的onSaveInstanceState方法,重写添加一些系统不会自动保存的数据,同时,使用其他变量。
需要长期存储的,使用数据库,files,或者SharedPreferences ,缓存存在catch文件中。
最重要的是根据优缺点的分辨使用几种保护。
5.编写合适的例子?
例子我就不写了,最简单的方式,写一个屏幕旋转,然后保存数据,就可以了,网上一把。
 
说明:本文引用了其他人文章的一些内容,经过自己测试,感谢这写人,记不清了,文章中写了主要地址。小子愚钝,错误请指教