简介
在我们平常开发的时候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之前使用。