《Fragment的一些整理》

Fragment是嵌套入Activity的片段,比Activity要更为轻巧灵活,但是用起来也会相对比较麻烦一些。之前在学习Fragment和实际开发中遇到一些Fragment的问题,所以就这些问题进行了整理。

一、Fragment的初始化

Google源码中一般采用newInstance的静态方法来新建一个fragment,建议用setArgument的方式来传递参数,将所需的参数直接暴露出来,方便一起开发的同事知道需要传什么数据。

《Fragment的一些整理》_第1张图片


二、屏幕旋转带来的问题

1、配置如下属性,限制Fragment托管的Activity旋转

  android:configChanges = "orientation|screenSize">

2、保留Fragment

用setRetainInstance(true)方法保留fragment实例。fragment的retainInstance属性值默认是false,表明fragment默认不会被保留。在屏幕旋转时,fragment的托管activity会被销毁重建,FragmentManager会销毁队列中的fragment视图,接着会检查retainInstance属性,如果属性是false(默认值),FragmentManager就会销毁该fragment。如果为true,该fragment的视图会被销毁,fragment本身并不销毁,新的FragmentManager会找到它,并给他创建新视图。但是,如果系统因为内存不足而销毁了托管的Activity,被保留的Fragment也会被销毁。


《Fragment的一些整理》_第2张图片

3、savedInstanceState

在Activity中我们可以通过onSaveInstanceState()方法和onRestoreInstanceState()方法实现数据的存储。

《Fragment的一些整理》_第3张图片

Fragment的保存机制和Activity类似,不过FragmentmyonRestoreInstanceState()方法,需要在onActivityCreated()中实现。

《Fragment的一些整理》_第4张图片

4、View的保存

在视图被销毁之后如果想要保存View的state,需要实现onSaveInstanceState()方法和onRestoreInstanceState()方法。安卓自带的View一般已经实现了这个方法,开发者在使用的时候只需要添加android:freezeText=”true”属性。

关于Fragment的保存,一篇外国博文做了较为详细的介绍。The Real Best Practices to Save/Restore Activity's and Fragment's state. (StatedFragment is now deprecated)

三、FragmentTransaction 的 add和remove、show和hide、replace的使用

transaction.add()

往Activity中添加一个Fragment

transaction.remove()

从Activity中移除一个Fragment,如果被移除的Fragment在没有添加到回退栈的情况下,这个Fragment实例将会被销毁。

transaction.replace()

使用另一个Fragment替换当前的。

transaction.hide()

隐藏当前的Fragment

transaction.show()

显示之前隐藏的Fragment

替换fragment

使用replace切换:

使用replace切换回调用一下2段life cycle

05-08 07:44:30.554 2864-2864/? D/_Albert: FirstFragment:onAttch

05-08 07:44:30.554 2864-2864/? D/_Albert: FirstFragment:onCreate

05-08 07:44:30.554 2864-2864/? D/_Albert: FirstFragment:onCreateView

05-08 07:44:30.561 2864-2864/? D/_Albert: FirstFragment:onActivityCreated

05-08 07:44:30.561 2864-2864/? D/_Albert: FirstFragment:onStart

05-08 07:44:30.561 2864-2864/? D/_Albert: FirstFragment:onResume



05-08 07:44:43.010 2864-2864/? D/_Albert: FirstFragment:onPause

05-08 07:44:43.011 2864-2864/? D/_Albert: FirstFragment:onStop

05-08 07:44:43.011 2864-2864/? D/_Albert: FirstFragment:onDestoryView

05-08 07:44:43.011 2864-2864/? D/_Albert: FirstFragment:onDestory

05-08 07:44:43.011 2864-2864/? D/_Albert: FirstFragment:onDetach

05-08 07:44:43.011 2864-2864/? D/_Albert: ReplaceFragment:onAttch

05-08 07:44:43.011 2864-2864/? D/_Albert: ReplaceFragment:onCreate

05-08 07:44:43.011 2864-2864/? D/_Albert: ReplaceFragment:onCreateView

05-08 07:44:43.015 2864-2864/? D/_Albert: ReplaceFragment:onActivityCreated

05-08 07:44:43.015 2864-2864/? D/_Albert: ReplaceFragment:onStart

05-08 07:44:43.016 2864-2864/? D/_Albert: ReplaceFragment:onResume

也就是说,replace会remove掉之前的fragment,再将替换fragment,add进去。

使用add、show、hide切换:

life cycle 如下:

05-08 08:16:44.818 3740-3740/? D/_Albert: FirstFragment:onAttch

05-08 08:16:44.819 3740-3740/? D/_Albert: FirstFragment:onCreate

05-08 08:16:44.819 3740-3740/? D/_Albert: FirstFragment:onCreateView

05-08 08:16:44.824 3740-3740/? D/_Albert: FirstFragment:onActivityCreated

05-08 08:16:44.825 3740-3740/? D/_Albert: FirstFragment:onStart

05-08 08:16:44.825 3740-3740/? D/_Albert: FirstFragment:onResume

05-08 08:16:55.383 3740-3740/? D/_Albert: SecondFragmentonAttch

05-08 08:16:55.383 3740-3740/? D/_Albert: SecondFragmentonCreate

05-08 08:16:55.383 3740-3740/? D/_Albert: SecondFragmentonCreateView

05-08 08:16:55.384 3740-3740/? D/_Albert: SecondFragment:onActivityCreated

05-08 08:16:55.384 3740-3740/? D/_Albert: SecondFragment:onStart

05-08 08:16:55.384 3740-3740/? D/_Albert: SecondFragment:onResume

以上生命周期的对比表明replace方法会remove之前的fragment,而用add搭配hide方法只是将之前的fragment做一个隐藏,并不会触发他的life cycle。在实际开发中,如果要保留一面用户操作界面的建议不要采用replace方法去切换。

四、getActivity为null的坑

Fragment中的Context的我们一般利用getActivity()来获取托管的Activity()作为Context使用。

而getActivity有时会null。

一种做法是保持对Activity的引用。

@Override

public voidonAttach(Activity activity) {

super.onAttach(activity);

mContext= activity;

}

getActivity()==null一般出现在Fragment和Activity没有关联的情况。较为稳妥的做法是找到没关联的原因。如果确定已经onAttach()过了,问题大多出现在onDetach()里面。原因可能是托管的Activity已经被销毁。或者Fragment的实例被删去之后View没有被赋值mContainerView,导致UI一直在。

你可能感兴趣的:(《Fragment的一些整理》)