Reputation: 942
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
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
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
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