创建Fragment使用 构造函数 还是 newInstance()

来源:互联网 发布:lumia安装软件 编辑:程序博客网 时间:2024/05/18 00:57

Creating a Fragment: constructor vs newInstance()

from stack overflow

and another chapter

最近,我厌倦了在创造Fragments 字符串参数传给Bundles的重要性。因此,我决定在构造函数中设置参数,并把这些参数放入Bundle


public ImageRotatorFragment() {    super();    Log.v(TAG, "ImageRotatorFragment()");}public ImageRotatorFragment(int imageResourceId) {    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");    // Get arguments passed in, if any    Bundle args = getArguments();    if (args == null) {        args = new Bundle();    }    // Add parameters to the argument bundle    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);    setArguments(args);}

然后我拿出 这些参数普通方式一样。

@Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    Log.v(TAG, "onCreate");    // Set incoming parameters    Bundle args = getArguments();    if (args != null) {        mImageResourceId = args.getInt(KEY_ARG_IMAGE_RES_ID, StaticData.getImageIds()[0]);    }    else {        // Default image resource to the first image        mImageResourceId = StaticData.getImageIds()[0];    }}

然而,提示问题说   没有与其他参数的构造函数片段的子类,要求我使用@ suppresslint(“validfragment”)才能运行应用程序。

事情是,这个代码非常好。我可以用imagerotatorfragment(int imageresourceid)

public static ImageRotatorFragment newInstance(int imageResourceId) {    Log.v(TAG, "newInstance(int imageResourceId)");    ImageRotatorFragment imageRotatorFragment = new ImageRotatorFragment();    // Get arguments passed in, if any    Bundle args = imageRotatorFragment.getArguments();    if (args == null) {        args = new Bundle();    }    // Add parameters to the argument bundle    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);    imageRotatorFragment.setArguments(args);    return imageRotatorFragment;}

我个人认为使用构造比知道使用的newInstance(),并传递参数一个更普遍的做法。我相信你可以使用带有活动同样的构造技术,林特不会抱怨。所以基本上我的问题是,为什么谷歌不希望你使用构造与片段参数?


我唯一的猜测是,所以你不要试图在不使用捆绑,这不会得到设置时,片段被重新设置一个实例变量。通过使用一个静态的newInstance()方法时,编译器不会让你访问一个实例变量
public ImageRotatorFragment(int imageResourceId) {    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");    mImageResourceId = imageResourceId;}

我仍然不觉得这是足够的理由来禁止在构造函数中使用的参数。任何人都见识到这一点?

1#

我个人认为使用构造比知道使用的newInstance(),并传递参数一个更普遍的做法

工厂方法模式的被使用非常频繁的现代软件开发

所以基本上我的问题是,为什么谷歌不希望你使用带片段参数 的构造方法?

You answered your own question:

don't try to set an instance variable without(没有) using the Bundle, which won't get set when the Fragment gets recreated(重新创建).

Correct.

我仍然不觉得这是足够的理由来禁止在构造函数中使用的参数。


#2

编辑:虽然这个工程,可以是有用的,它是危险的,因为私有字段设置一次使用这种模式改变的方向和引用的时候,通常是从以前浏览过的片段,也许不会被保留,可以由系统回收内存被清除。使用捆绑,使解析的,建议你的对象。


我所遇到的使用的newInstance这意味着你不必叫setArguments或getArguments,这意味着你不仅限于数据类型,你可以在一个包设置一个很好的实例化模式。


片段需要有空的构造,以使系统重新实例化时重新实例化碎片和碎片的构造与参数将不会被调用。因此,使用的newInstance是一个更好的主意,实际添加的对象引用和数据的片段实例。


我也真的不喜欢使用setArguments,getArguments。这是额外的代码和null检查,只是似乎限制,你可以只设置Parcelable的和原始类型。您还需要额外的锅炉板代码来设置静态密钥名称字符串等等...


所以,你可以达到同样的效果,如下:


private int resourceId;private SomeView someView; private OtherObject otherObject;// empty constructor to allow fragment re-instantiationpublic ImageRotatorFragment() {}public static ImageRotatorFragment newInstance(int resourceId, SomeView someView, OtherObject otherObject) {    ImageRotatorFragment fragment = new ImageRotatorFragment();    fragment.resourceId = resourceId;    fragment.someView = someView;    fragment.otherObject = otherObject;    return fragment;}


public class TestFragment extends Fragment {    private static final String TAG = "TestFragment";    private String hello;// = "hello android";    private String defaultHello = "default value";    static TestFragment newInstance(String s) {        TestFragment newFragment = new TestFragment();        Bundle bundle = new Bundle();        bundle.putString("hello", s);        newFragment.setArguments(bundle);        return newFragment;    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.d(TAG, "TestFragment-----onCreate");        Bundle args = getArguments();        hello = args != null ? args.getString("hello") : defaultHello;    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {        Log.d(TAG, "TestFragment-----onCreateView");        View view = inflater.inflate(R.layout.lay1, container, false);        TextView viewhello = (TextView) view.findViewById(R.id.tv_hello);        viewhello.setText(hello);        return view;    }    @Override    public void onDestroy() {        super.onDestroy();        Log.d(TAG, "TestFragment-----onDestroy");    }}
1 0
原创粉丝点击