I've a project that I want to migrate to Navigation Architecture Components.
Before the migration, I have an activity that has a fragment that hosts a ViewPager
; and I can access a method in this fragment from the ViewPager
adapter fragment by referencing the host fragment tag that I had set in the fragment transaction:
MyFragment fragment = (MyFragment ) ((MyActivity) requireActivity())
.getSupportFragmentManager().findFragmentByTag("fragment_tag");
fragment.someMethodInMyFragment();
Here is a diagram that deceits a part of the migration, and what I need to access through the yellow arrow:
In Navigation components, I didn't find a chance to set a tag to the destination fragment that hosts the ViewPager
, so that I can access it through the tag like before. Also, the ViewPager
adapter fragments are not a part of the Navigation components.
What I have tried: In the ViewPager
adapter fragment:
Attempt 1
MyFragment fragment = (MyFragment) getParentFragment(); // This returns the navigation host fragment. So ClassCastException is raised
fragment.someMethodInMyFragment();
Attempt 2
MyFragment fragment = (MyFragment) requireActivity().getSupportFragmentManager()
.findFragmentById(R.id.myFragment); // id of myFragment in the nav graph.
fragment.someMethodInMyFragment(); // fragment is null
UPDATE:
posting ViewPager
adapter
public class PageFragmentPagerAdapter extends FragmentStatePagerAdapter {
public PageFragmentPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@NonNull
@Override
public Fragment getItem(int position) {
return MyPagerFragment.newInstance(position);
}
@Override
public int getCount() {
return 10;
}
}
And I setup the ViewPager in MyFragment
like below
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager viewPager = view.findViewById(R.id.viewpager);
PageFragmentPagerAdapter adapter = new PageFragmentPagerAdapter(requireActivity()
.getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
Your problem is that you are using requireActivity().getSupportFragmentManager()
as the FragmentManager
for your adapter.
Instead, you should always use getChildFragmentManager()
for Fragments that are fully contained within another fragment - you'll note that under configuration changes or process death and recreation, this is required to restore the state of each Fragment correctly.
When you use the child FragmentManager, then requireParentFragment()
will return the correct fragment that you're looking for.