该文章来自于我偶然逛知乎看到的一位答主所总结的,感觉总结的很好,拿来给大家分享、学习一下。
在Android3.0以后Fragment被大量的投入使用,然而在开发中会遇到很多问题,比如重建activity会导致多重fragment出现,fragment复杂的生命周期等影响,然而fragment带来的
强大的优势毕竟相比于Activity来说,却可以让我们选择这个利大于弊的fragment。然而很多fragment出现的问题往往是因为使用不当而造成多的。于是在我闲逛知乎的时候就
偶然的发现的下面这位技术很好的答主的回答。
作者:面条
链接:https://www.zhihu.com/question/39662488/answer/82469372
来源:知乎
强大的优势毕竟相比于Activity来说,却可以让我们选择这个利大于弊的fragment。然而很多fragment出现的问题往往是因为使用不当而造成多的。于是在我闲逛知乎的时候就
偶然的发现的下面这位技术很好的答主的回答。
作者:面条
链接:https://www.zhihu.com/question/39662488/answer/82469372
来源:知乎
fragment一般分为两类,一类是有UI的fragment,可以作为页面,作为View来展示,另一类是用没有UI的fragment,一般用作保存数据。
- 继承基类
public abstract class BaseFragment extends Fragment {
protected View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(null == mRootView){
mRootView = inflater.inflate(getLayoutId(), container, false);
}
return mRootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
afterCreate(savedInstanceState);
}
protected abstract int getLayoutId();
protected abstract void afterCreate(Bundle savedInstanceState);
}
不过有一点,public View onCreateView 这个方法中返回之前判断一下你的mRootView是null再inflate,这样会比较好,在ViewPager中随着页面滑动这个方法会调用多次,inflate过了之后就直接用就好了。
- 使用静态工厂方法newInstance(...)来获取Fragment实例
还有就是Fragment推荐使用setArguments来传递参数,避免在横竖屏切换的时候Fragment自动调用自己的无参构造函数,导致数据丢失。
public static WeatherFragment newInstance(String cityName) {
Bundle args = new Bundle();
args.putString(cityName,"cityName");
WeatherFragment fragment = new WeatherFragment();
fragment.setArguments(args);
return fragment;
}
- 状态保存/现场恢复
不要在Fragment里面保存ViewState!
不要在Fragment里面保存ViewState!
为了让你的代码更加清晰和稳定,最好区分清楚fragment状态保存和view状态保存,
如果某个属性属于View,则不要在Fragment中做它的状态保存,除非属性属于Fragment。
每一个自定义View都有义务实现状态的保存,可以像EditText一样,设置一个开关来选择是否保存
比如说:android:freezeText="true/false"。
public class CustomView extends View {
...
@Override
public Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
// 在这里保存当前状态
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
// 恢复保存的状态
}
...
}
处理fragment状态保存,例如保存从服务器获取的数据。
private String serverData;
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("data", serverData);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
serverData = savedInstanceState.getString("data");
}
- 避免错误操作导致Fragment的视图重叠
public class WeatherFragment extends Fragment {
//TAG
public static final String TAG = WeatherFragment.class.getSimpleName();
不过为了最大限度的重用,可以在Activity的onCreate(Bundle savedInstanceState)中判断savedInstanceState是否不为空;
不为空的话,先用getSupportFragmentManager(). findFragmentByTag()找一下,找到实例就不用再次创建。
WeatherFragment fragment = null;
if(savedInstanceState!=null){
fragment = getSupportFragmentManager().findFragmentByTag(WeatherFragment.TAG);
}
if(fragment == null){
fragment = WeatherFragment.newInstance(...);
}
- 使用最大化的DialogFragment来实现浮动层级视图
不过这并不是最好的做法,在要考虑到Tablet适配的情况下,如下图


Tablet上是嵌入的,而手机上是占据全部空间。
此时可以把详情页单纯用Fragment实现,满足Tablet设备嵌入的需要,在手机上可以使用全屏的DialogFragment来包裹Fragment,之后只需要DialogFragment.show(...)即可。
从这里就可以看出,Fragment的使用其实是非常灵活的。
- 判断一个页面该使用Fragment还是Activity
例如SplashActivity和MainActivity没有太多的耦合度,此时可以分成两个Activity。