174

我正在使用Fragments其中一个创建一个应用程序,我创建了一个非默认构造函数并收到此警告:

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

有人能告诉我为什么这不是一个好主意吗?

你能否建议我如何做到这一点:

public static class MenuFragment extends ListFragment {
    public ListView listView1;
    Categories category;

    //this is my "non-default" constructor
    public MenuFragment(Categories category){
        this.category = category;
    }....

不使用非默认构造函数?

4

6 回答 6

278

似乎没有一个答案真正回答“为什么使用 bundle 来传递参数而不是非默认构造函数”

您应该通过 bundle 传递参数的原因是因为当系统恢复 a fragment(例如在配置更改时)时,它会自动恢复您的bundle.

回调喜欢onCreateonCreateView应该从中读取参数bundle- 这样您可以保证将状态fragment正确恢复到初始化时使用的相同状态fragment(注意此状态可能与onSaveInstanceState bundle传递给的状态不同onCreate/onCreateView

使用静态newInstance()方法的建议只是一个建议。您可以使用非默认构造函数,但请确保在bundle该构造函数的主体内部填充初始化参数。onCreate()并在oronCreateView()方法中读取这些参数。

于 2013-04-16T16:53:58.417 回答
112

制作一个捆绑对象并插入您的数据(在本例中为您的Category对象)。请注意,您不能将此对象直接传递到包中,除非它是可序列化的。我认为最好在片段中构建你的对象,并且只将一个 id 或其他东西放入包中。这是创建和附加捆绑包的代码:

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);

之后,在您的片段访问数据中:

Type value = getArguments().getType("key");

就这样。

于 2012-08-21T22:08:50.620 回答
52

Fragment不应该有构造函数,因为它是如何FragmentManager实例化的。您应该newInstance()使用所需的参数定义一个静态方法,然后将它们捆绑并将它们设置为片段的参数,稍后您可以使用Bundle参数访问它。

例如:

public static MyFragment newInstance(int title, String message) {
    MyFragment fragment = new MyFragment();
    Bundle bundle = new Bundle(2);
    bundle.putInt(EXTRA_TITLE, title);
    bundle.putString(EXTRA_MESSAGE, message);
    fragment.setArguments(bundle);
    return fragment ;
}

并在以下位置阅读这些论点onCreate

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    title = getArguments().getInt(EXTRA_TITLE);
    message = getArguments().getString(EXTRA_MESSAGE);

    //...
}

这样,如果分离并重新附加,对象状态可以通过参数存储,就像bundles附加到Intents。

于 2013-03-25T09:58:20.000 回答
9

如果您对某些类使用参数。尝试这个

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}
于 2015-01-16T05:07:59.910 回答
1

我认为,静态构造函数和两个构造函数(将参数存储到 Fragment 的参数包中的空且参数化的构造函数)之间没有区别,最有可能的是,创建此经验法则是为了减少忘记在 Java 中实现无参数构造函数的可能性,在存在过载时不会隐式生成。

在我的项目中,我使用 Kotlin,并使用主要的无参数构造函数和辅助构造函数来实现片段,这些构造函数只是将它们存储到一个包中并将其设置为片段参数,一切正常。

于 2017-07-26T11:07:01.087 回答
0

如果片段在配置更改后使用非默认构造函数,片段将丢失所有数据。

于 2020-03-15T21:02:38.637 回答