简体   繁体   English

Android片段实例化:newInstance()

[英]Android Fragment instantiation: newInstance()

I read many articles and StackOverflow answers but still cannot understand why we need a factory method to create an instance of a Fragment. 我阅读了许多文章和StackOverflow答案,但仍然无法理解为什么我们需要工厂方法来创建Fragment的实例。

The following Fragment classes both work fine. 下面的Fragment类都可以正常工作。

Fragment with two constructors: 具有两个构造函数的片段:

public class CtorFragment extends Fragment {
    private static final String KEY = "the_key";

    public CtorFragment() {
        // Android calls the default constructor so default constructor must be explicitly defined.
        // As we have another constructor, Android won't create a default constructor for us.
    }

    public CtorFragment(String s) {
        // Set the arguments.
        Bundle bundle = new Bundle();
        bundle.putString(KEY, s);

        setArguments(bundle);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View fragment = inflater.inflate(R.layout.fragment_my, container, false);
        TextView textView = (TextView) fragment.findViewById(R.id.textView);

        // Use getArguments() to get the String argument set by the constructor with parameter.
        textView.setText(getArguments().getString(KEY));
        return fragment;
    }
}

Fragment with a static factory method: 使用静态工厂方法的片段:

public class StaticFragment extends Fragment {
    private static final String KEY = "the_key";

    public static StaticFragment newInstance(String s) {
        StaticFragment fragment = new StaticFragment();
        // Set the arguments.
        Bundle bundle = new Bundle();
        bundle.putString(KEY, s);

        fragment.setArguments(bundle);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View fragment = inflater.inflate(R.layout.fragment_my, container, false);
        TextView textView = (TextView) fragment.findViewById(R.id.textView);

        // Use getArguments() to get the String argument set by the constructor with parameter.
        textView.setText(getArguments().getString(KEY));
        return fragment;
    }
}

Can you please explain why everyone (including Google) "strongly recommends" the one with the static factory method? 您能否解释一下为什么每个人(包括Google)都使用静态工厂方法“强烈推荐”一个? Is there something critical that me and others coming from a non-Android background missing? 我和其他来自非Android背景的人是否有一些重要的问题?

Is it that we have to define two methods (constructors) instead of one (static factory method) which causes all the fuss? 是不是我们必须定义两个方法(构造函数),而不是一个会引起大惊小怪的方法(静态工厂方法)?

The purpose of the newInstance is mainly to set initial value for the Fragment. newInstance的目的主要是为Fragment设置初始值。 If we using a default constructor for the fragment, we can't set the arguments as a means for sending the initial value. 如果我们对片段使用默认的构造函数,则无法将参数设置为发送初始值的手段。


Here is the more details explanation, quoting from https://stackoverflow.com/a/9245510/4758255 : 这是更详细的解释,引用https://stackoverflow.com/a/9245510/4758255

If Android decides to recreate your Fragment later, it's going to call the no-argument constructor of your fragment. 如果Android决定稍后再创建片段,它将调用片段的无参数构造函数。 So overloading the constructor is not a solution. 因此,重载构造函数不是解决方案。

With that being said, the way to pass stuff to your Fragment so that they are available after a Fragment is recreated by Android is to pass a bundle to the setArguments method. 话虽如此,将内容传递给Fragment以便在Android重新创建Fragment后可用的方法是将包传递给setArguments方法。

So, for example, if we wanted to pass an integer to the fragment we would use something like: 因此,例如,如果我们想将整数传递给片段,我们将使用类似以下内容:

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

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

    return myFragment;
}

And later in the Fragment onCreate() you can access that integer by using: 然后在Fragment onCreate()您可以使用以下方式访问该整数:

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

This Bundle will be available even if the Fragment is somehow recreated by Android. 即使Fragment是由Android重新创建的,此Bundle仍然可用。

Also note: setArguments can only be called before the Fragment is attached to the Activity. 另请注意:只能在将Fragment附加到Activity之前调用setArguments

This approach is also documented in the android developer reference: https://developer.android.com/reference/android/app/Fragment.html android开发人员参考中也记录了这种方法: https : //developer.android.com/reference/android/app/Fragment.html

still cannot understand why we need a factory method to create an instance of a Fragment 仍然不明白为什么我们需要一个工厂方法来创建一个Fragment的实例

"Need" is a strong word. “需要”是一个很强的词。 You do not "need" a factory method. 您不需要“需要”工厂方法。 You do need: 需要:

  • A public zero-argument constructor, ideally empty; 一个公共的零参数构造函数,理想情况下为空; and

  • An organized means to set up a fragment, in a way that survives configuration changes 一种有条理的方式来设置片段,以便在配置更改后不受影响

Can you please explain why everyone (including Google) "strongly recommends" the one with the static factory method? 您能否解释一下为什么每个人(包括Google)都使用静态工厂方法“强烈推荐”一个?

If you have no explicit constructors on a Java class, you automatically get an empty public zero-argument constructor, which is what the framework needs to create a fragment. 如果Java类上没有显式构造函数,则将自动获得一个空的公共零参数构造函数,这是框架创建片段所需要的。

If you create a constructor that takes arguments (eg, CtorFragment(String s) ), then you also have to remember to create the public zero-argument constructor ( CtorFragment() ). 如果您创建一个接受参数的构造函数(例如CtorFragment(String s) ),则还必须记住要创建公共零参数构造函数( CtorFragment() )。 You might remember to do this. 您可能记得这样做。 Many inexperienced programmers will not. 许多没有经验的程序员不会。

Writing a factory method achieves the same objective as the non-zero-arguments constructor, without clobbering the automatically-created zero-argument constructor. 编写工厂方法可实现与非零参数构造函数相同的目标,而不会破坏自动创建的零参数构造函数。

If you are an experienced Java programmer, and you do not like factory methods, and you can read stack traces and otherwise remember to add the public zero-argument constructor, you are welcome to create additional constructors and use them. 如果您是一位经验丰富的Java程序员,并且不喜欢工厂方法,可以阅读堆栈跟踪,否则请记住添加公共零参数构造函数,欢迎您创建其他构造函数并使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM