View的onSaveInstanceState和onRestoreInstanceState

本文介绍了自定义View中onSaveInstanceState和onRestoreInstanceState的使用,通过分析源码理解这两个方法的调用流程。在保存实例状态时,通过SavedState类保存View的状态,而在恢复状态时,从SavedState对象中获取并恢复。同时,文章提醒开发者注意view的id不能为空,以确保状态正确保存和恢复。源码分析部分揭示了这两个方法在View、ViewGroup和Activity中的调用细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

日常的开发过程中难免会自定义一些view,view的状态数据保存及恢复也是需要考虑进内的,就会用到onSaveInstanceState和onRestoreInstanceState这两个方法。

onSaveInstanceState

顾名思义,保存实例状态。以CompoundButton为例:

    @Override
    public Parcelable onSaveInstanceState() {
   
   
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.checked = isChecked();
        return ss;
    }

该方法返回的是一个序列化对象,即SavedState,checked状态也是保存在该对象里面,看一下该类的实现:

    static class SavedState extends BaseSavedState {
   
   
        boolean checked;

        /**
         * Constructor called from {@link CompoundButton#onSaveInstanceState()}
         */
        SavedState(Parcelable superState) {
   
   
            super(superState);
        }

        /**
         * Constructor called from {@link #CREATOR}
         */
        private SavedState(Parcel in) {
   
   
            super(in);
            checked = (Boolean)in.readValue(null);
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
   
   
            super.writeToParcel(out, flags);
            out.writeValue(checked);
        }

        @Override
        public String toString() {
   
   
            return "CompoundButton.SavedState{"
                    + Integer.toHexString(System.identityHashCode(this))
                    + " checked=" + checked + "}";
        }

        @SuppressWarnings("hiding")
        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
   
   
            @Override
            public SavedState createFromParcel(Parcel in) {
   
   
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
   
   
                return new SavedState[size];
            }
        };
    }

代码简单,整个类即是序列化的实现,该类继承BaseSavedState,BaseSavedState在View里面定义,用于保存View的状态。BaseSavedState继承AbsSavedState,AbsSavedState则实现了Parcelable。代码就不贴了,在我们的自定义view里面,比葫芦画瓢,也实现一个继承BaseSavedState的类,把需要保存的状态利用该类保存即可。

onRestoreInstanceState

顾名思义,恢复实例状态。还是看CompoundButton的代码:

    @Override
    public void onRestoreInstanceState(Parcelable state) {
   
   
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        setChecked(ss.checked);
        requestLayout();
    }

onSaveInstanceState返回的是SavedState对象,该方法会将SavedState对象传递过来,强制类型转换之后,先将父View的状态恢复过去,再从该对象里面拿到之前保存的状态进行恢复即可。
以上即是自定义view的状态保存的基本用法,到这里还不够,我们需要阅读一下源码,看一下如上两个方法是如何调用的,才能知其然,遇到问题时知道如何分析。

源码分析

所有的view的根view均是android.view.View,可以从这里下手看看上面两个方法是怎么调用的。调用onSaveInstanceState的代码如下:

    /**
     * Store this view hierarchy's frozen state into the given container.
     *
     * @param container The SparseArray in which to save the view's state.
     *
     * @see #restoreHierarchyState(android.util.SparseArray)
     * @see #dispatchSaveInstanceState(android.util.SparseArray)
     * @see #onSaveInstanceState()
     */
    public void saveHierarchyState(SparseArray<Parcelable> container) {
   
   
        dispatchSaveInstanceState(container);
    }

    /**
     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
     * this view and its children. May be overridden to modify how freezing happens to a
     * view's children; for example, some views may want to not store state for their children.
     *
     * @param container The SparseArray in which to save the view's state.
     *
     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
     * @see #saveHierarchyState(android.util.SparseArray)
     * @see #onSaveInstanceState()
     */
    protected void dispatchSaveInstanceState
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值