Fragment具有属性retainInstance,默认值为false。
当设备旋转时,fragment会随托管activity一起销毁并重建。
调用setRetainInstance(true)方法可保留fragment,示例代码如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
...........
}
已保留的fragment不会随着activity一起被销毁;
相反,它会一直保留(进程不消亡的前提下),并在需要时原封不动地传递给新的Activity。
保留Fragment的原理是:
当设备配置发生变化时,FragmentManager首先销毁队列中fragment的视图(因为可能有更合适的匹配资源);
紧接着,FragmentManager将检查每个fragment的retainInstance属性值。
如果retainInstance属性值为false,FragmentManager会立即销毁该fragment实例。
随后,为适应新的设备配置,新的Activity的新的FragmentManager会创建一个新的fragment及其视图。
如果retainInstance属性值为true,则该fragment的视图立即被销毁,但fragment本身不会被销毁。
为适应新的设备配置,当新的Activity创建后,新的FragmentManager会找到被保留的fragment,并重新创建其试图。
虽然保留的fragment没有被销毁,但它已脱离消亡中的activity并处于保留状态。
尽管此时的fragment仍然存在,但已经没有任何activity托管它,其生命周期如下图所示:
需要说明的是:
只有调用了fragment的setRetainInstance(true)方法,
并且因设备配置改变,托管Activity正在被销毁的条件下,
fragment才会短暂的处于保留状态。
如果activity是因操作系统需要回收内存而被销毁,则所有的fragment也会随之销毁。
相对而言,onSaveInstanceState可以更长久的保持数据。
当Activity所在进程被系统杀死(非用户主动关闭),系统重新创建activity时,
将恢复onSaveInstanceState中保留的数据。
从上文我们知道,当Fragment设置了setRetainInstance(true)后,
在设备旋转等情况下,该Fragment可以暂时与Activity分离。
如果此时Fragment持有的后台线程,例如AsyncTask中的后台操作等,
需要使用Fragment的Context等信息,就可能出现错误。
为此,Fragment中定义了isAdded接口,
用于判断Fragment是否已经绑定到某个Activity。