Fragment.setArguments()的初愿

Fragment.setArguments()的初衷。

简介

在我们平常开发的时候Fragment是经常使用的,而我们创建一个Fragment对象的时候一般都会 通过 new Fragment()构造方法来实现,如果要传递参数我们一般会重载构造方法,例如 new Fragment(Parameter p)。

但是这样的做法是不被提倡的,如果你重载构造函数之后,系统会有一个warning,如下:

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

这个警告的意思就是,尽量避免使用 不是默认的构造函数(也就是我们重载的构造函数):通过 使用默认的构造函数 加上 Fragment.setArguments(Bundle)来取代。

接下来我们来看一下这两种方式:

重载的构造函数:

public class MyFragment extends Fragment {

    public MyFragment(MyParameter p){
        //将参数保存起来
    }

}

如果在创建Fragment的时候,使用 MyFragment mf = new MyFragment(parameter)
来传递参数。

通过Fragment.setArguments(Bundle)

public class MyFragment extends Fragment {

    public static MyFragment newInstance(int someInt) {
        MyFragment myFragment = new MyFragment();

        Bundle args = new Bundle();
        args.putInt("someInt", someInt);
        myFragment.setArguments(args);

        return myFragment;
    }
}

这种方式在创建Fragment的时候,使用MyFragment mf = MyFragment.newInstance(paramter) 来传递参数。

分析

乍一看这两种方法似乎没有什么本质区别,但是实际上 方法一(重载构造函数)是有一个隐患的。

根据Android文档说明,当一个fragment重新创建的时候,系统会再次调用 Fragment中的默认构造函数。 注意这里:是 默认构造函数

这句话更直白的意思就是:当你小心翼翼的创建了一个带有重要参数的Fragment的之后,一旦由于什么原因(横竖屏切换)导致你的Fragment重新创建。——-很遗憾的告诉你,你之前传递的参数都不见了,因为recreate你的Fragment的时候,调用的是默认构造函数

对比

而使用系统推荐的 Fragment.setArguments(Bundle)来传递参数。就可以有效的避免这一个问题,当你的Fragment销毁的时候,其中的Bundle会保存下来,当要重新创建的时候会检查Bundle是否为null,如果不为null,就会使用bundle作为参数来重新创建fragment.

疑问:

当fragment重建的时候,怎么获取之前的参数呢?
以上面的代码为例:我们可以重写 fragment的onCreate()方法。

getArguments().getInt("someInt", 0);

当fragment重现创建,调用onCreate方法,然后就可以取得之前的参数了,然后就可以尽情使用了。

bundle是如何将参数保存下来,然后重建的时候再利用呢?

这个问题可以移步这篇博客。

注意:

setArguments can only be called before the Fragment is attached to the Activity.

setArguments方法的调用必须要在Fragment与Activity关联之前。

这句话可以这样理解,setArgument方法的使用必须要在FragmentTransaction 的commit之前使用。
详见:连接。

参考资料1:

参考资料2

参考资料3