Android原理——SavedState
View.BaseSavedState
引言
还在用public static T 保存View状态?
Android官方早已想到了:
使用View的BaseSavedState来保存状态。
在一个activity被销毁前,不一定会调用onSaveInstanceState()这个方法,因为不是所有情况都需要去存储activity的状态(例如当用户按回退键退出你的activity的时候,因为用户指定关掉这个activity)。
如果这个方法被调用,它一定会在 onStop()方法之前,可能会在onPause()方法之前。
布局中的每一个View默认实现了onSaveInstanceState()方法,这样的话,这个UI的任何改变都会自动的存储和在activity重新创建的时候自动的恢复。但是这种情况只有在你为这个UI提供了唯一的ID之后才起作用,如果没有提供ID,将不会存储它的状态。
由于默认的onSaveInstanceState()方法的实现帮助UI存储它的状态,所以如果你需要覆盖这个方法去存储额外的状态信息时,你应该在执行任何代码之前都调用父类的onSaveInstanceState()方法(super.onSaveInstanceState())。
由于onSaveInstanceState()方法调用的不确定性,你应该只使用这个方法去记录activity的瞬间状态(UI的状态)。不应该用这个方法去存储持久化数据。当用户离开这个activity的时候应该在onPause()方法中存储持久化数据(例如应该被存储到数据库中的数据)。
类概述
BaseSavedState
Base class for derived classes that want to save and restore their own state in onSaveInstanceState().
直接子类
TextView.SavedState
ViewPager.SavedState
How To Use
读取保存状态
onRestoreInstanceState(Parcelable state)
保存状态
Parcelable onSaveInstanceState()
举个ViewPager.SavedState的示例
/**
* 读取保存状态
* */
@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;
}
/**
* 保存界面状态
* */
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);
}
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源码
我们看一下它的构造方法
public static class BaseSavedState extends AbsSavedState {
/**
* Constructor used when reading from a parcel. Reads the state of the superclass.
*
* @param source
*/
public BaseSavedState(Parcel source) {
super(source);
}
/**
* Constructor called by derived classes when creating their SavedState objects
*
* @param superState The state of the superclass of this view
*/
public BaseSavedState(Parcelable superState) {
super(superState);
}
public static final Parcelable.Creator<BaseSavedState> CREATOR =
new Parcelable.Creator<BaseSavedState>() {
public BaseSavedState createFromParcel(Parcel in) {
return new BaseSavedState(in);
}
public BaseSavedState[] newArray(int size) {
return new BaseSavedState[size];
}
};
}
而其父类实现了Parcelable
借口
/**
* A {@link Parcelable} implementation that should be used by inheritance
* hierarchies to ensure the state of all classes along the chain is saved.
*/
public abstract class AbsSavedState implements Parcelable {
public static final AbsSavedState EMPTY_STATE = new AbsSavedState() {};
private final Parcelable mSuperState;
/**
* Constructor used to make the EMPTY_STATE singleton
*/
private AbsSavedState() {
mSuperState = null;
}
/**
* Constructor called by derived classes when creating their SavedState objects
*
* @param superState The state of the superclass of this view
*/
protected AbsSavedState(Parcelable superState) {
if (superState == null) {
throw new IllegalArgumentException("superState must not be null");
}
mSuperState = superState != EMPTY_STATE ? superState : null;
}
/**
* Constructor used when reading from a parcel. Reads the state of the superclass.
*
* @param source
*/
protected AbsSavedState(Parcel source) {
// FIXME need class loader
Parcelable superState = source.readParcelable(null);
mSuperState = superState != null ? superState : EMPTY_STATE;
}
final public Parcelable getSuperState() {
return mSuperState;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mSuperState, flags);
}
public static final Parcelable.Creator<AbsSavedState> CREATOR
= new Parcelable.Creator<AbsSavedState>() {
public AbsSavedState createFromParcel(Parcel in) {
Parcelable superState = in.readParcelable(null);
if (superState != null) {
throw new IllegalStateException("superState must be null");
}
return EMPTY_STATE;
}
public AbsSavedState[] newArray(int size) {
return new AbsSavedState[size];
}
};
}
补充
最后再举一个定义SeekBar的
3 import android.content.Context;
4 import android.content.res.TypedArray;
5 import android.os.Parcel;
6 import android.os.Parcelable;
7 import android.util.AttributeSet;
8 import android.view.View;
9 import android.view.ViewGroup;
10 import android.view.ViewParent;
11
12 import com.WazaBe.HoloEverywhere.LayoutInflater;
13 import com.WazaBe.HoloEverywhere.R;
14 import com.WazaBe.HoloEverywhere.widget.SeekBar;
15
16 public class SeekBarDialogPreference extends DialogPreference {
17 private static class SavedState extends BaseSavedState {
18 @SuppressWarnings("unused")
19 public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
20 @Override
21 public SavedState createFromParcel(Parcel in) {
22 return new SavedState(in);
23 }
24
25 @Override
26 public SavedState[] newArray(int size) {
27 return new SavedState[size];
28 }
29 };
30
31 protected int mValue, mMaxValue;
32
33 public SavedState(Parcel source) {
34 super(source);
35 mValue = source.readInt();
36 mMaxValue = source.readInt();
37 }
38
39 public SavedState(Parcelable superState) {
40 super(superState);
41 }
42
43 @Override
44 public void writeToParcel(Parcel dest, int flags) {
45 super.writeToParcel(dest, flags);
46 dest.writeInt(mValue);
47 dest.writeInt(mMaxValue);
48 }
49 }
50
51 private final SeekBar mSeekBar;
52 private int mValue = Integer.MIN_VALUE, mMaxValue = Integer.MIN_VALUE;
53
54 public SeekBarDialogPreference(Context context) {
55 this(context, null);
56 }
57
58 public SeekBarDialogPreference(Context context, AttributeSet attrs) {
59 this(context, attrs, R.attr.seekBarDialogPreferenceStyle);
60 }
61
62 public SeekBarDialogPreference(Context context, AttributeSet attrs,
63 int defStyle) {
64 super(context, attrs, defStyle);
65 TypedArray a = context.obtainStyledAttributes(attrs,
66 R.styleable.SeekBarDialogPreference, defStyle,
67 R.style.Holo_PreferenceDialog_SeekBarDialogPreference);
68 int maxValue = a.getInt(R.styleable.SeekBarDialogPreference_max, 100);
69 a.recycle();
70 mSeekBar = onCreateSeekBar();
71 setMaxValue(maxValue);
72 }
73
74 public int getMaxValue() {
75 return mMaxValue;
76 }
77
78 public SeekBar getSeekBar() {
79 return mSeekBar;
80 }
81
82 public int getValue() {
83 return mValue;
84 }
85
86 @Override
87 protected void onBindDialogView(View view) {
88 super.onBindDialogView(view);
89 synchronized (mSeekBar) {
90 ViewParent oldParent = mSeekBar.getParent();
91 if (oldParent != view) {
92 if (oldParent != null) {
93 ((ViewGroup) oldParent).removeView(mSeekBar);
94 }
95 ((ViewGroup) view).addView(mSeekBar);
96 }
97 }
98 }
99
100 protected SeekBar onCreateSeekBar() {
101 return (SeekBar) LayoutInflater.inflate(getContext(),
102 R.layout.preference_dialog_seekbar_widget);
103 }
104
105 @Override
106 protected void onDialogClosed(boolean positiveResult) {
107 super.onDialogClosed(positiveResult);
108 final int value;
109 synchronized (mSeekBar) {
110 value = mSeekBar.getProgress();
111 }
112 if (positiveResult && callChangeListener(value)) {
113 setValue(value);
114 }
115 }
116
117 @Override
118 protected Integer onGetDefaultValue(TypedArray a, int index) {
119 return a.getInt(index, 0);
120 }
121
122 @Override
123 protected void onRestoreInstanceState(Parcelable state) {
124 if (state == null || !(state instanceof SavedState)) {
125 super.onRestoreInstanceState(state);
126 return;
127 }
128 SavedState ss = (SavedState) state;
129 super.onRestoreInstanceState(ss.getSuperState());
130 setValue(ss.mValue);
131 setMaxValue(ss.mMaxValue);
132 }
133
134 @Override
135 protected Parcelable onSaveInstanceState() {
136 final Parcelable superState = super.onSaveInstanceState();
137 if (isPersistent()) {
138 return superState;
139 }
140 final SavedState myState = new SavedState(superState);
141 myState.mValue = mValue;
142 myState.mMaxValue = mMaxValue;
143 return myState;
144 }
145
146 @Override
147 protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
148 int def = defaultValue instanceof Integer ? (Integer) defaultValue
149 : defaultValue == null ? 0 : Integer.parseInt(defaultValue
150 .toString());
151 mSeekBar.setProgress(restoreValue ? getPersistedInt(def) : def);
152 }
153
154 public void setMaxValue(int maxValue) {
155 if (mMaxValue == maxValue) {
156 return;
157 }
158 final boolean wasBlocking = shouldDisableDependents();
159 mMaxValue = maxValue;
160 mSeekBar.setMax(maxValue);
161 if (shouldDisableDependents() != wasBlocking) {
162 notifyDependencyChange(!wasBlocking);
163 }
164 }
165
166 public void setValue(int value) {
167 if (mValue == value) {
168 return;
169 }
170 final boolean wasBlocking = shouldDisableDependents();
171 mValue = value;
172 mSeekBar.setProgress(value);
173 persistInt(value);
174 if (shouldDisableDependents() != wasBlocking) {
175 notifyDependencyChange(!wasBlocking);
176 }
177 }
178 }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。