Henry Gunawan
Henry Gunawan

Reputation: 942

getArguments return null when passing data between fragments

I have 2 fragments called MedListFragment and MedDetailFragment. In MedListFragment there is a listview with items of Medicine object. When an item is clicked, MedDetailFragment will open with Medicine object passed from MedListFragment.This is the on item click listener in 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();
    }
});

Then in MedDetailFragment, I get the bundle like this:

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;
    }
}

But it returns error on line Medicine medicine = bundle.getParcelable("medicine"); saying:

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

Why are the arguments turn null? How exactly to get the bundle? Any help would be appreciated.

Upvotes: 0

Views: 1075

Answers (3)

user10496632
user10496632

Reputation: 473

In the lines

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

You instantiated a MedDetailFragment fragment, and added your arguments. Thus far all prerequisites were done and medDetailFragment is ready for use. Now it's time to add it to the placeholder say fragment_container. But in the line

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

you created a new instance of the fragment once again with the statement new using default constructor that creates a pure instance of MedDetailFragment fragment with no additional data (bundle object). Obviously calling getArguments() on this instance of the fragment tries to invoke a non-existing part of the fragment causing it to produce java.lang.NullPointerException.

Solution:

In MedListFragment class you have to replece the extra new MedDetailFragment() statement in line

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

with medDetailFragment you'd created previously.

Optimization:

It's highly recommended to use factory method approach in case of dealing with Fragments. To do so, class MedDetailFragment should look like :

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;
    }
}

and in class MedListFragment you should simply replace the two lines

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

with just a single line of code:

MedDetailFragment medDetailFragment = MedDetailFragment.newInstance(med);

This approach encapsulates the mechanism within MedDetailFragment class, it's much simpler and easy to debug.

I hope it helps.

Upvotes: 0

Zahoor Saleem
Zahoor Saleem

Reputation: 634

you are passing the new object that's why you getting he null

replace the following line

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

with

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

Upvotes: 0

Rajnish suryavanshi
Rajnish suryavanshi

Reputation: 3424

Take a look at these lines

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

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

You are creating two different object of MedDetailFragment. And not passing the object in which you have added the bundle.

Change this Line

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

Upvotes: 2

Related Questions