Activity状态恢复与保存的时候发生了什么?
我们都知道Activity状态保存的时候是通过onSaveInstancestate
方法,那这个方法具体做了什么呢?
- 手动保存成员变量数据
-
自动收集
View Hierarchy
(视图层次)中每一个View的状态。
save.gif
那恢复状态时调用的onRestoreInstanceState
方法又做了什么呢?
- 手动将保存的成员变量数据重新赋值
-
自动把收集的View数据恢复到每一个View中。
restore.gif
看到这里,大家也许会有一个疑问,为什么成员变量需要手动恢复,而View中的数据可以自动恢复呢。
原因就是这些View中实现了保存和恢复数据的方法,系统的控件TextView、checkBox等全部都实现了这两个方法。实现了这两个方法的第三方控件也是可以自动恢复保存的。
@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恢复数据的时候时根据其Android:id
指定的id来恢复的,因此没有定义Android:id
的View是不能够自动恢复的。
Fragment状态恢复与保存的时候发生了什么?
Fragment状态恢复与保存的过程和Activity是类似的,先给出动图示意。
与Activity不同的是,Fragment没有
onRestoreInstanceState
方法。我们要恢复数据,需要从onActivityCreated
方法中恢复。
public class TestFragment extends Fragment {
// These variable are destroyed along with Activity
private int VarA;
private String VarB;
...
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("VarA", VarA);
outState.putString("VarB", VarB);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
VarA = savedInstanceState.getInt("VarA");
VarB = savedInstanceState.getString("VarB");
}
}
还有一个重要的不同之处是与Fragment回退栈有关系的。
Fragment生命周期.png
从图中可以看到,Fragment可以通过两种途径来从前台退出。
- 使用导航栏中的回退键或者Fragment直接被
removed
和replaced
。 - Fragment先被添加到回退栈中,然后再被
removed
和replaced
。
第一种情况,该Fragment实例被销毁。
第二种情况,该Fragment的实例依然存在,但是其View被销毁。从图中可以看出在执行onDestroyView
方法之后,如果该Fragment从回退栈中又放到前台的话,其onCreateView
方法会被调用,重建视图而不是重建Fragment实例。
所以在第二种情况下,Fragment中的成员变量是自动保存下来的,因为本来其就没有被销毁啊。
Fragment与View的正确使用
从上文得知,如果View中有保存和恢复数据的方法的话,在其设置了Android:id的情况下,是能够自动恢复的。所以我们在使用View的时候,应该在View的内部实现保存恢复功能,而不应该是在Fragment中实现该功能。因为这样有利于Fragment与View的状态分开处理,也有利于代码的整洁。
所幸Android提供的控件都是实现了保存和恢复数据的方法的。而对于那些没有实现的第三方控件我们应该实现它的子类,手动实现这两个方法。
网友评论