我已经看到了在应用程序中实例化一个新Fragment的两个通用实践:

Fragment newFragment = new MyFragment();

and

Fragment newFragment = MyFragment.newInstance();

第二个选项使用静态方法newInstance(),通常包含以下方法。

public static Fragment newInstance() 
{
    MyFragment myFragment = new MyFragment();
    return myFragment;
}

起初,我认为主要的好处是,我可以重载newInstance()方法,以便在创建新的Fragment实例时提供灵活性——但我也可以通过为Fragment创建重载构造函数来实现这一点。

我错过什么了吗?

一种方法相对于另一种方法有什么好处?还是说这只是一个很好的练习?


当前回答

setArguments()没有用。这只会带来混乱。

public class MyFragment extends Fragment {

    public String mTitle;
    public String mInitialTitle;

    public static MyFragment newInstance(String param1) {
        MyFragment f = new MyFragment();
        f.mInitialTitle = param1;
        f.mTitle = param1;
        return f;
    }

    @Override
    public void onSaveInstanceState(Bundle state) {
        state.putString("mInitialTitle", mInitialTitle);
        state.putString("mTitle", mTitle);
        super.onSaveInstanceState(state);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
        if (state != null) {
            mInitialTitle = state.getString("mInitialTitle");
            mTitle = state.getString("mTitle");
        } 
        ...
    }
}

其他回答

使用newInstance()的唯一好处是:

You will have a single place where all the arguments used by the fragment could be bundled up and you don't have to write the code below everytime you instantiate a fragment. Bundle args = new Bundle(); args.putInt("someInt", someInt); args.putString("someString", someString); // Put any other arguments myFragment.setArguments(args); Its a good way to tell other classes what arguments it expects to work faithfully(though you should be able to handle cases if no arguments are bundled in the fragment instance).

因此,我认为使用静态newInstance()来实例化一个片段是一个很好的实践。

使用kotlin代码创建片段的实例。

在活动中写入

val fragment = YourFragment.newInstance(str = "Hello",list = yourList)

分段写作

fun newInstance(str: String, list: ArrayList<String>): Fragment {
        val fragment = YourFragment()
        fragment.arguments = Bundle().apply {
            putSerializable("KEY_STR", str)
            putSerializable("KEY_LIST", list)
        }
        return fragment
    }

使用相同的片段从bundle中检索数据

val str = arguments?.getString("KEY_STR") as? String
val list = arguments?.getSerializable("KEY_LIST") as? ArrayList<String>

还有另一种方法:

Fragment.instantiate(context, MyFragment.class.getName(), myBundle)

一些kotlin代码:

companion object {
    fun newInstance(first: String, second: String) : SampleFragment {
        return SampleFragment().apply {
            arguments = Bundle().apply {
                putString("firstString", first)
                putString("secondString", second)
            }
        }
    }
}

你可以得到这样的论点:

val first: String by lazy { arguments?.getString("firstString") ?: "default"}
val second: String by lazy { arguments?.getString("secondString") ?: "default"}

我最近在这里。但我知道的一些事也许能帮到你。

如果您正在使用Java,那么没有什么需要更改的。但是对于Kotlin开发人员来说,下面是一些代码片段,我认为它们可以让你成为一个运行的基础:

父母片段:

inline fun <reified T : SampleFragment> newInstance(text: String): T {
    return T::class.java.newInstance().apply {
        arguments = Bundle().also { it.putString("key_text_arg", text) }
    }
}

正常调用

val f: SampleFragment = SampleFragment.newInstance("ABC")
// or val f = SampleFragment.newInstance<SampleFragment>("ABC")

你可以在子fragment类中扩展父init操作:

fun newInstance(): ChildSampleFragment {
    val child = UserProfileFragment.newInstance<ChildSampleFragment>("XYZ")
    // Do anything with the current initialized args bundle here
    // with child.arguments = ....
    return child
}

快乐的编码。