为什么我要避免片段中的非默认构造函数?

Bla*_*rai 168 android android-fragments

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

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

不使用非默认构造函数?

num*_*ati 258

似乎没有一个答案实际回答"为什么使用bundle传递参数而不是非默认构造函数"

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

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

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

  • 您不再可以使用非默认构造函数(无论出于何种原因)....它会产生编译器错误(曾经是一个警告). (4认同)
  • 好解释.谢谢.如果我是那个问这个问题的人,我会给你一个勾号 (2认同)
  • 最好的答案就在底部! (2认同)

nis*_*v4n 107

创建一个bundle对象并插入你的数据(在这个例子中是你的Category对象).请注意,除非可序列化,否则不能将此对象直接传递到包中.我认为在片段中构建对象更好,并且只将id或其他内容放入bundle中.这是创建和附加包的代码:

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);
Run Code Online (Sandbox Code Playgroud)

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

Type value = getArguments().getType("key");
Run Code Online (Sandbox Code Playgroud)

就这样.

  • Bundles可以携带序列化的Java对象以及[`Parcelable`](http://developer.android.com/reference/android/os/Parcelable.html)对象.此外,您不应该传递`Context`,因为可以通过片段的[`getActivity()`方法]访问该信息(http://developer.android.com/reference/android/app/Fragment.html#getActivity ()). (12认同)
  • @Muhammad Babar:如果我是你,我会把它添加到`newInstance()`方法中.例如:`public static FragmentName newInstance(your variables){}`.正如Android文档所建议的那样,不要使用参数创建构造函数,因为在重新启动片段后将自动调用默认值(不带参数). (4认同)
  • 如何传递一个物体?我想传递一个Context Object或任何其他对象. (3认同)

Asa*_*ssi 50

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 ;
}
Run Code Online (Sandbox Code Playgroud)

并阅读这些论点onCreate:

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

    //...
}
Run Code Online (Sandbox Code Playgroud)

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


小智 9

如果您为某些类使用参数.试试这个

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是一个糟糕的建议.一旦Fragment将由`FragmentManager`重新创建,您将失去mSomeInstance. (5认同)