Activity的状态保存

来源:互联网 发布:材料数据库 编辑:程序博客网 时间:2024/05/16 22:17
我们在上篇文章中说道,当 Activity 暂停或停止时,Activity 的状态会得到保留。 确实如此,因为当 Activity 暂停或停止时,Activity 对象仍保留在内存中 — 有关其成员和当前状态的所有信息仍处于活动状态。 因此,用户在 Activity 内所做的任何更改都会得到保留,这样一来,当 Activity 返回前台(当它“继续”)时,这些更改仍然存在。
但是,当系统为了恢复内存而销毁某项 Activity 时,Activity 对象也会被销毁,因此系统在继续 Activity 时根本无法让其状态保持完好,而是必须在用户返回 Activity 时重建 Activity 对象。但用户并不知道系统销毁 Activity 后又对其进行了重建,因此他们很可能认为 Activity 状态毫无变化。 在这种情况下,您可以实现另一个回调方法对有关 Activity 状态的信息进行保存,以确保有关 Activity 状态的重要信息得到保留:onSaveInstanceState()

系统会先调用 onSaveInstanceState(),然后再使 Activity 变得易于销毁。系统会向该方法传递一个 Bundle,您可以在其中使用 putString() 和 putInt() 等方法以名称-值对形式保存有关 Activity 状态的信息。然后,如果系统终止您的应用进程,并且用户返回您的 Activity,则系统会重建该 Activity,并将Bundle同时传递给 onCreate()onRestoreInstanceState()。您可以使用上述任一方法从 Bundle 提取您保存的状态并恢复该 Activity 状态。如果没有状态信息需要恢复,则传递给您的 Bundle 是空值(如果是首次创建该 Activity,就会出现这种情况)。

此图Activity屏幕转换的时候,未保存数据的状态:


此时没有在相应的回调方法中进行数据保存与恢复,就会导致屏幕的旋转过程中数据的丢失,回调的方法如下:


我们若想保存和恢复数据只需要在对应的方法下进行存取操作即可:

利用Bundle进行存储数据

    protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        outState.putString("data",show.getText().toString());    }
通过Bundle进行取数据:

    @Override    protected void onRestoreInstanceState(Bundle savedInstanceState) {        super.onRestoreInstanceState(savedInstanceState);        show.setText((CharSequence) savedInstanceState.get("data"));    }
效果图如下:


(注意:onSaveInstanceState()方法会在onPause和onStop之间调用,若想保存数据我们需要明确能够走到的生命周期,比如上一篇文章中说到的透明activity就只会走到Onpause,在onpause状态时若被系统干掉,那么就不能保存数据,一般来说保存数据的操作是写在onPause方法中,恢复数据的操作是写在oncreate方法中,这样可以确定被系统回调)

分享一点自己的经验,可能有些小伙伴们写一些UI组件比如Editex或者spinner等,在操作这些组件的时候即使不进行保存操作,系统也会帮我们保存数据,这是因为这些类的父类中定义了此方法:

    public Parcelable onSaveInstanceState() {        Parcelable superState = super.onSaveInstanceState();        // Save state if we are forced to        final boolean freezesText = getFreezesText();        boolean hasSelection = false;        int start = -1;        int end = -1;        if (mText != null) {            start = getSelectionStart();            end = getSelectionEnd();            if (start >= 0 || end >= 0) {                // Or save state if there is a selection                hasSelection = true;            }        }
这是TextView中定义的保存的方法返回的是一个parcel对象,它是由freezesText的状态和Id共同决定的,若freezesText的属性为true并且给定Id。那么我们在对此组件进行操作就会自动保存数据,有意思的是,谷歌考虑到用户体验等问题,给Editex的freezsText的属性设置为true且不可更改。因此我们在自定义组件的时候,应该注意这个问题。


0 0
原创粉丝点击