您的位置:首页 > 其它

自定义控件基础 onSaveInstanceState()

2016-03-30 13:19 405 查看
在看JakeWharton的ViewPagerIndicator时,在CircleIndicator中的onSaveInstanceState()中保存了当前的page信息,于是就学习这块。

介绍:

onSaveInstanceState()是在Activity被异常回收时会被调用,正常情况下不会调用该方法。Activity重建时会调用onRestoreInstanceState()方法,进行恢复数据。

我们在写自定义控件时,如果有必要,则要复写这两个方法。

异常情况有:

资源相关的系统配置发生改变,导致Activity被杀死并重新创建。比如旋转屏幕等。

系统资源内存不足导致低优先级的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);
}


原理:

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

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

保存数据的条件:

必须要有ID。因为底层通过sparseArray保存数据,ViewId作为key存在。

ViewId必要要独立。unique。所有状态都保存在一个sparseArray中,相同的id会造成覆盖。

参考:

能极大促进理解:

Saving Android View state correctly

自定义控件中SaveState写法:

stackoverflow
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: