Android,使用activity与fragment的小结与使用的细节

来源:互联网 发布:淘宝和拍拍网的区别 编辑:程序博客网 时间:2024/06/14 01:04

该文章来自于我偶然逛知乎看到的一位答主所总结的,感觉总结的很好,拿来给大家分享、学习一下。

  在Android3.0以后Fragment被大量的投入使用,然而在开发中会遇到很多问题,比如重建activity会导致多重fragment出现,fragment复杂的生命周期等影响,然而fragment带来的
强大的优势毕竟相比于Activity来说,却可以让我们选择这个利大于弊的fragment。然而很多fragment出现的问题往往是因为使用不当而造成多的。于是在我闲逛知乎的时候就
偶然的发现的下面这位技术很好的答主的回答。


作者:面条
链接:https://www.zhihu.com/question/39662488/answer/82469372
来源:知乎

fragment一般分为两类,一类是有UI的fragment,可以作为页面,作为View来展示,另一类是用没有UI的fragment,一般用作保存数据。

  • 继承基类
例如为了实例化View,抽象一个getLayoutId方法,子类无需关心具体的创建操作,父类来做View的创建处理。同时可以提供一个afterCreate抽象函数,在初始化完成之后调用,子类可以做一些初始化的操作,你也可以添加一些常用的方法在基类,例如ShowToast().


 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实例
可以在Google的代码中发现这种写法,好处是接收确切的参数,返回一个Fragment实例,避免了在创建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里面保存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的视图重叠
这个问题很简单,在add或者replace的时候,调用含有TAG参数的那个方法,之后再add相同TAG的Fragment的话,之前的会被替换掉,也就不会同时出现多个相同的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来实现浮动层级视图
如果你有一个列表页面,例如知乎,点击Item打开详情页,你可以使用最大化的DialogFragment来显示详情页,此时并不需要提供一个具体的ContainerId即可显示,因为详情页一般情况下在Phone上都是占据满屏幕的,用DialogFragment即可。

不过这并不是最好的做法,在要考虑到Tablet适配的情况下,如下图

Tablet上是嵌入的,而手机上是占据全部空间。

此时可以把详情页单纯用Fragment实现,满足Tablet设备嵌入的需要,在手机上可以使用全屏的DialogFragment来包裹Fragment,之后只需要DialogFragment.show(...)即可。

从这里就可以看出,Fragment的使用其实是非常灵活的。

  • 判断一个页面该使用Fragment还是Activity
如果后一个页面不需要用到前一个页面的太多数据,推荐用Activity展示,否则最好用Fragment( 当然这也不是绝对的)。

例如SplashActivity和MainActivity没有太多的耦合度,此时可以分成两个Activity。



0 0
原创粉丝点击