翻译老外的文章,写的不错,也可以自己去看,地址。
当Activity的 onSaveInstanceState被调用,Activity自动会按照View层级获取每一个View的状态信息。注意,Activity只能获取覆写了Saving/RestoringState方法的View 的状态。一旦onRestoreInstanceState被调用, Activity会按照View层级一个一个发送保存的状态至View(根据android:id判断不同的View)。
来看一下动态图!
这就是当Activity被摧毁重建而在EditText输入的内容依然存在的原因。这并不是魔术,这些View的状态会自动保存并还原,这也是为什么一个View没有定义id(android:id)的话状态会丢失的原因。
尽管这些View的状态会自动保存,Activity的成员变量却并不会。它们会随着Activity一同被摧毁,你必须手动覆写onSaveInstanceState和 onRestoreInstanceState方法来保存/还原它们。
public class MainActivity extends AppCompatActivity {
// These variable are destroyed along with Activity
private int someVarA;
private String someVarB;
...
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("someVarA", someVarA);
outState.putString("someVarB", someVarB);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
someVarA = savedInstanceState.getInt("someVarA");
someVarB = savedInstanceState.getString("someVarB");
}
}
这就是所有关于保存Activity状态和View状态你需要做的。
这意味着每一个成员变量都会被摧毁,你必须手动通过onSaveInstanceState 和onActivityCreated方法保存/恢复这些变量,需要注意的是Fragment中没有提供 onRestoreInstanceState 方法。
public class MainFragment extends Fragment {
// These variable are destroyed along with Activity
private int someVarA;
private String someVarB;
...
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("someVarA", someVarA);
outState.putString("someVarB", someVarB);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
someVarA = savedInstanceState.getInt("someVarA");
someVarB = savedInstanceState.getString("someVarB");
}
}
一旦Fragment从返回站中弹出,他的View会被摧毁和重建,这一点与Activity不同。
在这种情况下,Fragment不会destroyed,只有Fragment中的 View才会。
所以要想保存View状态,View必须覆写Saving/RestoringState方法,例如EditText或TextView,只需加上android:freezeText="true",就会自动保存并恢复状态。
请记住在这种情况下,只有View会被摧毁和重建,Fragment没有任何变化,所以它的成员是不变的,这一点与Activity不同!
public class MainFragment extends Fragment {
// These variable still persist in this case
private int someVarA;
private String someVarB;
...
}
是的,你注意到了,只有View覆写那两个保存/还原状态的方法,我们不需要做任何事,所以说:
public class CustomView extends View {
...
@Override
public Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
// Save current View's state here
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
// Restore View's state here
}
...
}
Android的基础View。例如EditText, TextView, Checkbox and etc都实现了这些方法,我们需要做的就是将android:freezeText设为true即可使用这些特性。
如果你决定使用一些第三方自定义的View,如果它们没有覆写那两个方法,你必须手动实现这两个方法。
//
// Assumes that SomeSmartButton is a 3rd Party view that
// View State Saving/Restoring are not implemented internally
//
public class SomeBetterSmartButton extends SomeSmartButton {
...
@Override
public Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
// Save current View's state here
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
// Restore View's state here
}
...
}
如果你在写自定义View或Viewgroup,同样不要忘记覆写这两个方法,它真的很重要。
同样不要忘记为你的View赋予id(android:id),如果没有id,Android不会保存这些View的状态!
要清楚Fragment状态与View状态是不同的概念
为了确保你的code是整洁的,可扩展的,你必须吧Fragment和View 状态分开。如果一个属性是属于View的,那么请把它的保存恢复工作放到View的saving/restoringstate 方法中,反之亦然。看一下示例:
public class MainFragment extends Fragment {
...
private String dataGotFromServer;
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("dataGotFromServer", dataGotFromServer);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dataGotFromServer = savedInstanceState.getString("dataGotFromServer");
}
...
}