在看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]; } }; }当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
新闻热点
疑难解答