Best practice for instantiating a new Android Fragment

前端 未结 13 1475
暖寄归人
暖寄归人 2020-11-21 04:38

I have seen two general practices to instantiate a new Fragment in an application:

Fragment newFragment = new MyFragment();

and

<         


        
13条回答
  •  终归单人心
    2020-11-21 05:08

    While @yydl gives a compelling reason on why the newInstance method is better:

    If Android decides to recreate your Fragment later, it's going to call the no-argument constructor of your fragment. So overloading the constructor is not a solution.

    it's still quite possible to use a constructor. To see why this is, first we need to see why the above workaround is used by Android.

    Before a fragment can be used, an instance is needed. Android calls YourFragment() (the no arguments constructor) to construct an instance of the fragment. Here any overloaded constructor that you write will be ignored, as Android can't know which one to use.

    In the lifetime of an Activity the fragment gets created as above and destroyed multiple times by Android. This means that if you put data in the fragment object itself, it will be lost once the fragment is destroyed.

    To workaround, android asks that you store data using a Bundle (calling setArguments()), which can then be accessed from YourFragment. Argument bundles are protected by Android, and hence are guaranteed to be persistent.

    One way to set this bundle is by using a static newInstance method:

    public static YourFragment newInstance (int data) {
        YourFragment yf = new YourFragment()
        /* See this code gets executed immediately on your object construction */
        Bundle args = new Bundle();
        args.putInt("data", data);
        yf.setArguments(args);
        return yf;
    }
    

    However, a constructor:

    public YourFragment(int data) {
        Bundle args = new Bundle();
        args.putInt("data", data);
        setArguments(args);
    }
    

    can do exactly the same thing as the newInstance method.

    Naturally, this would fail, and is one of the reasons Android wants you to use the newInstance method:

    public YourFragment(int data) {
        this.data = data; // Don't do this
    }
    

    As further explaination, here's Android's Fragment Class:

    /**
     * Supply the construction arguments for this fragment.  This can only
     * be called before the fragment has been attached to its activity; that
     * is, you should call it immediately after constructing the fragment.  The
     * arguments supplied here will be retained across fragment destroy and
     * creation.
     */
    public void setArguments(Bundle args) {
        if (mIndex >= 0) {
            throw new IllegalStateException("Fragment already active");
        }
        mArguments = args;
    }
    

    Note that Android asks that the arguments be set only at construction, and guarantees that these will be retained.

    EDIT: As pointed out in the comments by @JHH, if you are providing a custom constructor that requires some arguments, then Java won't provide your fragment with a no arg default constructor. So this would require you to define a no arg constructor, which is code that you could avoid with the newInstance factory method.

    EDIT: Android doesn't allow using an overloaded constructor for fragments anymore. You must use the newInstance method.

提交回复
热议问题