自定义控件基础 onSaveInstanceState()

在看JakeWharton的ViewPagerIndicator时,在CircleIndicator中的onSaveInstanceState()中保存了当前的page信息,于是就学习这块。

介绍:

onSaveInstanceState()是在Activity被异常回收时会被调用,正常情况下不会调用该方法。Activity重建时会调用onRestoreInstanceState()方法,进行恢复数据。
我们在写自定义控件时,如果有必要,则要复写这两个方法。

异常情况有:

  1. 资源相关的系统配置发生改变,导致Activity被杀死并重新创建。比如旋转屏幕等。
  2. 系统资源内存不足导致低优先级的Activity被杀死。

示例:

CircleIndicator部分代码如下:
这种写法也是自定义控件时标准写法。具体可查看文章底部链接。 可以查看TextView源码,这块也是这样写的。

    @Override
    //在该方法中恢复数据
    public void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState)state;
        super.onRestoreInstanceState(savedState.getSuperState());
        mCurrentPage = savedState.currentPage;
        mSnapPage = savedState.currentPage;
        requestLayout();
    }

    @Override
    //在该方法中进行保存数据
    public Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState savedState = new SavedState(superState);
        savedState.currentPage = mCurrentPage;
        return savedState;
    }

    //创建内部类,用于存储信息。继承BaseSavedState类。
    static class SavedState extends BaseSavedState {
        int currentPage;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            currentPage = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(currentPage);
        }

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

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

另一种写法

@Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable("superState", super.onSaveInstanceState());
        bundle.putInt("current_item", currentItem);
        bundle.putStringArray("notifications", notifications);
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            currentItem = bundle.getInt("current_item");
            notifications = bundle.getStringArray("notifications");
            state = bundle.getParcelable("superState");
        }
        super.onRestoreInstanceState(state);
    }

Fragment中:

@Override public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(EXTRA_PARCELABLE, a);
    }

//可获取
@Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

//可获取
 @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

    }


原理:

当Activity被意外终止,Activity会调用onSaveInstanceState()去保存数据,然后Activity委托Window去保存数据。Window再委托它上面的顶级容器去保存数据。顶层容器是一个ViewGroup,通过他再去一一通知它的子元素来保存数据。

这篇文章 Saving Android View state correctly 更加精细的讲解了这个过程。

保存数据的条件:

  1. 必须要有ID。因为底层通过sparseArray保存数据,ViewId作为key存在。
  2. ViewId必要要独立。unique。所有状态都保存在一个sparseArray中,相同的id会造成覆盖。


参考:

能极大促进理解:
Saving Android View state correctly

自定义控件中SaveState写法:
stackoverflow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baiiu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值