Activity状态保存与重建


主要方法

  • onSaveInstanceState(Bundle outState)
  • onRestoreInstanceState(Bundle savedInstanceState)

调用时机

  • onSaveInstanceState(Bundle outState)

    从Android P开始,该方法如果被调用,也是在onStop之后;

    在Android P之前,则会在onStop之前调用,但是不能保证是在onPause之前还是之后;

  • onRestoreInstanceState(Bundle savedInstanceState)

    onStart()之后,onPostCreate() 之前执行,并且只有在重新创建Activity的时候才会执行

    不过一般的实现是在onCreate()中拿到保存的bundle进行自定义的恢复逻辑;

    在onRestoreInstanceState()中会默认恢复View层级的状态信息.

onSaveInstanceState()在onStop之后都会执行(AndroidP前后版本可能会有所差异),但是onRestoreInstanceState()则只在某些特定的场景才会执行:

  • 在“开发者选项-不保留活动”中设置,从Activity A跳转到Activity B再返回,也会执行onRestoreInstanceState()

    这种情况下,Activity重建时可能会onResume()-onPause()-onResume();

  • App处于后台,被系统回收,导致Activity被销毁,当再次重启Activity的时候;

  • 配置信息变更的时候,比如屏幕方向切换的时候;

在onCreate()中的savedInstanceState有可能为null,而onRestoreInstanceState()中的savedInstanceState()则一定不为null;

保存了什么状态

各种状态都是保存到Bundle中的,如果有比较复杂的结构,就使用Parcelable.

主要存储了以下信息:

  • View层级中View的状态信息

    • 具有ID的View的信息
    • 拥有焦点的View的信息
    • 状态信息存储在不同View中的BaseSavedState中,这个类是一个Parcelable类
  • Fragment信息

  • Dialog信息

不同的View中可以有不同的BaseSavedState实现,用来保存各自的信息,比如在ViewPager2中保存的信息时当前选中的位置.

而且View中也有对应的onSaveInstanceState()方法,用于保存自身的状态信息.

保存在哪了

保存到了磁盘(及手机上的存储器)上(这一点存疑)

image-20201227184818533

持久化的问题

有一个PersistableBundle可以当作持久化的状态保存.

在onCreate(),onsaveInstanceState(),onRestoreInstanceState()中也有对应的参数传递.

但是目前在应用层很少使用这个类.

源码分析

state bundle的创建

在ActivityThread中有:

private void callActivityOnSaveInstanceState(ActivityClientRecord r) {
        r.state = new Bundle();
        r.state.setAllowFds(false);
        if (r.isPersistable()) {
            r.persistentState = new PersistableBundle();
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
                    r.persistentState);
        } else {
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
        }
    }

保存了什么状态

在Activity中有:

    final void performSaveInstanceState(@NonNull Bundle outState) {
        dispatchActivityPreSaveInstanceState(outState);

        // View层级信息
        onSaveInstanceState(outState);

        // Dialog信息
        saveManagedDialogs(outState);

        // Fragment信息
        mActivityTransitionState.saveState(outState);

        // 是否请求过权限
        storeHasCurrentPermissionRequest(outState);
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
        dispatchActivityPostSaveInstanceState(outState);
    }


    protected void onSaveInstanceState(@NonNull Bundle outState) {
        // View层级信息,mWindow最终也是通过DecorView去获取的层级信息
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

        // 自动填充的内容
        outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        if (mAutoFillResetNeeded) {
            outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
            getAutofillManager().onSaveInstanceState(outState);
        }
        dispatchActivitySaveInstanceState(outState);
    }

文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
Context.getSystemService()实现解析 Context.getSystemService()实现解析
Android中经常会通过context.getSystemService(Context.XX_Service),这里简单看一下实现方式. 在ContextImpl.java中有: @Override public Obj
2020-12-28
下一篇 
std::deque std::deque
C++中的std::deque,看名字就知道是一个双端队列. 容量操作// 容量大小 deq.size(); // 最大容量 deq.max_size(); // 更改容器大小 deq.resize(); // 容器判空 deq.e
2020-12-12
  目录