理解Fragment.newInstance方法

7
我正在实现一个Android片段。我知道框架可以自动销毁和重新创建片段,重新创建一个片段调用它的默认构造函数,而不是具有参数的构造函数。 有许多文章(例如这个问题的被接受答案)展示了如何通过实现静态newInstance方法来提供片段参数。
我不明白的是谁调用newInstance。我的第一印象是——因为可以为这个newInstance方法定义任意参数——我应该在应用程序中的某个地方添加一个显式调用,而newInstance名称仅是一种命名约定。但是,这样我就会创建除了由框架调用默认构造函数创建的片段之外的第二个片段,这让我很困惑。
那么上述假设是否不正确,并且newInstance方法实际上是Java中内置方法的某种重载方式?在这种情况下,我不明白如何定义一个带有任意参数列表的newInstance方法。或者,在Java中是否可能,而我只是不够了解Java?

2
是的,您需要在代码中调用 newInstance(),而空构造函数则由框架在需要重新创建时使用。 - Yazan
1
请注意,您是否在没有实例化的情况下使用了Fragment?即没有使用“...= new ...”? - Yazan
实际上,是的 - 它不使用 new。在活动布局的 XML 中,我有一个 <fragment> 元素,据我所知,这就是片段的实例化方式。我没有任何显式调用。无论如何,我不确定它是如何工作的。 - Dabbler
1
正确的,这种情况下的框架将使用空构造函数,没有参数,如果您直接使用new或使用newInstance(),则需要空构造函数来重新创建片段(如果它被销毁),newInstance不是重写方法,您可以随意命名它。 - Yazan
3个回答

11

您可以随意命名函数: newInstance, getInstance, newFragment。这并不重要,这只是一个辅助方法。重要的是将所有参数放入 fragment.setArguments(args) 中。Android 系统会记住这些参数,并在片段重新创建时使用它们。

public static MyFragment newInstance(int arg) {

    Bundle args = new Bundle();
    args.putInt("ARG", arg);

    MyFragment fragment = new MyFragment();
    fragment.setArguments(args);
    return fragment;
}

Android系统会记住这些参数,并在片段重新创建时使用它们。也许这就是我缺少的信息。所以,首先我通过newInstance创建片段。当Android随后重新创建片段时,它首先调用默认构造函数,然后调用setArguments并传入存储的参数? - Dabbler
如上所述,在活动布局的 XML 中,我有一个 <fragment> 元素,据我所知,这就是片段的实例化方式。那么这是如何工作的呢?也许我一开始就没有正确地创建活动。 - Dabbler
1
第一个问题:是的。请查看Fragment setArguments javadoc:“此处提供的参数将在片段销毁和创建时保留” 关于xml片段创建,请查看:https://dev59.com/Lmcs5IYBdhLWcg3wOBVC 有两种创建片段的方法:通过代码(然后调用newInstance())和使用XML标记。使用XML标记片段会自动由系统使用默认构造函数创建。因此,在这种情况下,您需要以不同的方式传递参数。在这种情况下,永远不会调用newInstance方法。 - Arkadiusz Konior
谢谢,Arkadiusz! - Dabbler

7
newInstance是一种Android设计模式,因为Fragment除默认构造函数外不应该有任何其他Constructor

因此,您需要定义一个帮助函数来传递参数给Fragment

如果您不使用帮助函数,则需要复制实例化Fragment的代码。

我不明白谁调用newInstance

通常,您将从创建Fragment的地方(如ActivityAdapter等)使用instantiate方法。

SectionPagerAdapter示例:

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class below).
        return PlaceholderFragment.newInstance(position + 1);
    }

PlaceholderFragment.newInstance(int position) 是什么

public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

在这种情况下,我不知道如何定义一个接受任意参数列表的新实例方法。您可以传递任意参数列表,但需要知道值类型 Type ,因为 Bundle 只有 putX() 方法,其中 X 是参数的类型。

3

Fragment.newInstance(args1,args2...)被用作静态构造方法。静态构造方法的好处不言而喻。但在Fragment中,这样做可以帮助我们保存参数,并且我们可以在onCreate()方法中获取这些参数,以便当您的应用程序出现问题时,Android可以使用没有参数的构造函数来恢复您的片段。

public static StudyFragment newInstance(ArrayList<DailyWordBean.DataBean> list) {
    Bundle args = new Bundle();
    args.putSerializable("data", list);
    StudyFragment fragment = new StudyFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        list = (ArrayList<DailyWordBean.DataBean>) getArguments().getSerializable("data");
        Log.e("study", list.size() + list.get(0).getWordContent());
    }
}

请记得使用Parcelable而不是Serializable


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接