购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

5.3 保存Activity的状态

5.3.1 Activity的状态保存简介

在Activity被意外销毁的情况下,使用onSaveInstanceState()和onRestoreInstanceState()方法保存Activity的状态,如UI组件的录入内容、滚动列表的滚动条位置等,并在销毁Activity之后,再次启动这个Activity的时候恢复之前保存的数据。

onSaveInstanceState()和onRestoreInstanceState()并不是生命周期方法,它们与生命周期方法被调用的时机也不一样,它们并不一定会被调用。只有当应用遇到意外情况,如:内存不足而被系统销毁、用户直接按Home键、开启了一个新的Activity等的时候,onSaveInstanceState()方法才会被回调。而当用户主动去销毁一个Activity的时候,如:按回退键后退、从任务管理器中关闭应用等情况,onSaveInstanceState()方法都不会被触发。原则上来说,就是被系统自动销毁的Activity的时候,会触发onSaveInstanceState()方法,而用户主动销毁的行为,将不会触发它。onRestoreInstanceState()方法,只有在确定是系统销毁的情况下,才会在下次Activity被启动的时候调用。因为它们的调用时机无法保证,所以onSaveInstanceState()方法只适合用于保存一些临时性的状态,而对于一些重要的数据,推荐使用生命周期方法onPause()方法进行数据持久化保存。

下图诠释了Activity状态保存的过程:

从上图可以看出,Activity状态的保存,调用的是onSaveInstanceState(),而恢复状态的时候,调用的是onCreate()或者onRestoreInstanceState()方法,下面是这三个方法的完整签名:

· void onCreate(Bundle savedInstanceState)

· void onStaveInstanceState(Bundle outState)

· void onRestoreInstanceState(Bundle savedInstanceState)

这三个方法都有一个Bundle的对象参数,这个Bundle对象就是用来保存于恢复数据而存在的,在意外销毁的时候,回调onSaveInstanceState()方法向Bundle对象中写入数据,在意外销毁之后启动Activity的时候,回调onCreate()或者onRestoreInstanceState()方法从Bundle对象中获取数据。Bundle内部维护了一个Map集合,所以可以把它看出一个Map集合来使用。

5.3.2 状态保存与恢复的时机

onSaveInstanceState()和onRestoreInstanceState()方法在Activity的整个生命周期中,并不一定会被调用,它们有不同的调用时机。

对于onSaveInstanceState()而言,只有在系统认为某个Activity因为系统的原因,变的"容易"被系统销毁时,该Activity的onSaveInstanceState()方法才会被回调执行。那么什么情况下是容易被系统销毁呢?不处于当前Task的最上层,不处于当前屏幕显示并可以获得焦点的时候。因为对于Android系统而言,只要不是前台显示的Activity,在系统内存不足的情况下,都认为它们是"容易"并且可以被销毁的。所以总结来说,有如下几种情况:

1. 当用户按下HOME键,退回桌面。

2. 长按HOME键,选择运行其它应用时。

3. 按下电源键,关闭屏幕显示时。

4. 从当前Activity中启动了一个新的Activity时。

5. 屏幕方向被切换时。

对于onRestoreInstanceState()方法而言,回调的前提是当前Activity确实已经被系统自行销毁了。Android系统的运行机制,决定了在内存足够的情况下,默认它是不会主动销毁应用来释放内存空间的,哪怕是用户主动退出应用的情况下,这样是为了下次开启这个应用时,初始化的速度更快,当然用户是可以主动从任务管理器中清理运行的应用以释放内存。所以这样的系统环境下,首先必须保证Activity的onSaveInstanceState()方法被回调,其次必须是被系统主动销毁之后,再此启动这个Activity,onRestoreInstanceState()方法才会被回调使用。

有一种特殊的情况,就是在默认情况下,Android设备的屏幕方向被改变的时候,会先触发onSaveInstanceState()方法伴随着Activity的销毁,然后触发onRestoreInstanceState()方法伴随着Activity的恢复。

基于这个特殊的情况,重写上面的实例,在Activity屏幕方向切换导致Activity被销毁的时候,保存文本框的内容,并在Activity被重新创建的时候恢复文本框的数据。

代码清单:\codes\05\03\SaveActivityStateDemo\src\com\bookdemo\saveactivitystatedemo\MainActivity.java

public class MainActivity extends Activity {
    private EditText etUsername;
    private final static String TAG = "main";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "---onCreate方法被回调---");

        etUsername = (EditText) findViewById(R.id.etUsername);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i("main", "---onSaveInstanceState方法被回调---");
        outState.putString("username", etUsername.getText().toString());
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        Log.i("main", "---onRestoreInstanceState方法被回调---");
        etUsername.setText(savedInstanceState.getString("username"));
        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onStart() {
        Log.i(TAG, "---onStart方法被回调---");
        super.onStart();
    }

    @Override
    protected void onRestart() {
        Log.i(TAG, "---onRestart方法被回调---");
        super.onRestart();
    }

    @Override
    protected void onResume() {
        Log.i(TAG, "---onResume方法被回调---");
        super.onResume();
    }

    @Override
    protected void onPause() {
        Log.i(TAG, "---onPause方法被回调---");
        super.onPause();
    }

    @Override
    protected void onStop() {
        Log.i(TAG, "---onStop方法被回调---");
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        Log.i(TAG, "---onDestroy方法被回调---");
        super.onDestroy();
    }
}

在模拟器上运行效果如下:

在这个实例中增加了对Activity生命周期的方法,可以查看LogCat输出的日志,观察Activity状态保存与恢复的方法及Activity生命周期方法的调用时机。

从LogCat输出的日志可以看出,onSvaeInstanceState()方法在生命周期方法onPause()与onStop()方法之间被调用,onRestoreInstanceState()方法在生命周期方法onStart()与onResume()方法之间被调用。

5.3.3 onSaveInstanceState()方法的默认实现

如果没有重写onSaveInstanceState()方法,Activity会使用自己维护的onSaveInstanceState()方法对Activity的UI组件状态进行自动保存,并在需要恢复的时候自动恢复。其实这里所谓的保存UI组件状态,也只是调用了UI组件本身的onSaveInstanceState()方法,Android UI组件均继承了View类,同样也都继承了View类的onSaveInstanceState()方法。但是View组件保存自己的状态,必须在这些UI组件被设置了ID属性的前提下。

因为Activity的onSaveInstanceState()方法还具有保存Activity中UI组件状态的功能,所以如果重写了onSaveInstanceState()方法,需要在其中调用父类的onSaveInstanceState()方法。 DcaDvoqg6qJO+3GxifN+GKAcUAk7XXPKjzno/8qdMtV5VWEcPQehYSA2kdU+Vxl4

点击中间区域
呼出菜单
上一章
目录
下一章
×