在片段之间传递数据时,getArguments return null

getArguments return null when passing data between fragments

我有 2 个片段,分别称为 MedListFragment 和 MedDetailFragment。在 MedListFragment 中有一个包含 Medicine 对象项的列表视图。当一个项目被点击时,MedDetailFragment 将打开 Medicine 对象,从 MedListFragment.This 是 MedListFragment 中的项目点击监听器。

MedListFragment

medlist = (ListView) root.findViewById(R.id.medlist);

medlist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Medicine med = (Medicine) adapterView.getItemAtPosition(i);

        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        Bundle bundle = new Bundle();
        bundle.putParcelable("medicine", med);

        MedDetailFragment medDetailFragment = new MedDetailFragment();
        medDetailFragment.setArguments(bundle);

        fragmentTransaction.replace(R.id.fragment_container, new MedDetailFragment());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
});

然后在 MedDetailFragment 中,我得到这样的包:

public class MedDetailFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_med_detail, container, false);

        Bundle bundle = getArguments();

        Medicine medicine = bundle.getParcelable("medicine");

        return root;
    }
}

但是 returns 行 Medicine medicine = bundle.getParcelable("medicine"); 错误说:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Parcelable android.os.Bundle.getParcelable(java.lang.String)' on a null object reference

为什么参数变为空?究竟如何获得捆绑包?任何帮助将不胜感激。

看看这些行

MedDetailFragment medDetailFragment = new MedDetailFragment();
medDetailFragment.setArguments(bundle);

fragmentTransaction.replace(R.id.fragment_container, new MedDetailFragment());

您正在创建两个不同的 MedDetailFragment 对象。并且不传递您添加包的对象。

更改此行

fragmentTransaction.replace(R.id.fragment_container,medDetailFragment );

你传递的是新对象,这就是为什么你得到他 null

替换下面一行

fragmentTransaction.replace(R.id.fragment_container, new MedDetailFragment());

fragmentTransaction.replace(R.id.fragment_container, medDetailFragment);

行中

MedDetailFragment medDetailFragment = new MedDetailFragment();
medDetailFragment.setArguments(bundle);

您实例化了一个 MedDetailFragment 片段,并添加了您的参数。 到目前为止,所有先决条件都已完成,medDetailFragment 可以使用了。 现在是时候将它添加到占位符 fragment_container 中了。 但是在行

fragmentTransaction.replace(R.id.fragment_container, new `MedDetailFragment`())

您使用默认构造函数再次使用语句 new 创建了片段的新实例,该构造函数创建了 MedDetailFragment 片段的纯实例,没有附加数据(bundle 对象) . 显然,在片段的这个实例上调用 getArguments() 会尝试调用片段的不存在部分,导致它产生 java.lang.NullPointerException.

解法:

MedListFragment class 中,您必须在行

中替换额外的 new MedDetailFragment() 语句
fragmentTransaction.replace(R.id.fragment_container, new MedDetailFragment());

使用您之前创建的 medDetailFragment

优化:

在处理 Fragments 的情况下,强烈建议使用工厂方法方法。为此,class MedDetailFragment 应如下所示:

public class MedDetailFragment extends Fragment {

    public MedDetailFragment() {
        // Required empty public constructor
    }

    public static MedDetailFragment newInstance(Medicine med) {
        Bundle bundle = new Bundle();
        bundle.putParcelable("medicine", med);
        MedDetailFragment medDetailFragment  = new MedDetailFragment();
        medDetailFragment.setArguments(bundle);
        return medDetailFragment;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_med_detail, container, false);

        Bundle bundle = getArguments();

        Medicine medicine = bundle.getParcelable("medicine");

        return root;
    }
}

和 class MedListFragment 你应该简单地替换这两行

MedDetailFragment medDetailFragment = new MedDetailFragment();
medDetailFragment.setArguments(bundle);

只需一行代码:

MedDetailFragment medDetailFragment = MedDetailFragment.newInstance(med);

这种方法封装了MedDetailFragmentclass中的机制,更简单,也更容易调试。

希望对您有所帮助。