I just ran into a problem in our project. The main reason is how the FragmentPagerAdapter works:
The FragmentPagerAdapter simply separates the fragment that is not currently needed from its view, but does not remove it from the FragmentManager. When he wants to display the fragment again, he will see if the FragmentManager saves the Fragment using a tag that is created from the ViewPager view identifier and the identifier returned by calling the adapter's getItemId (position) call. If he finds a fragment, he simply plans to bind the fragment to its representation in the update transaction of the FragmentManager. Only if he does not find the fragment in this way, he creates a new one using the adapter call getItem (position)!
The problem with the fragment containing the ViewPager with the FragmentPagerAdapter is that the contents of the FragmentManager are never cleared when the contained fragment is pushed onto the back stack. If the containing fragment returns from the back stack, it creates a new View, but the FragmentManager still contains the fragments that were attached to the old view, and the attachment of the existing fragment no longer works.
The easiest way to get rid of this problem is to avoid nested fragments. :)
The second easiest way, as mentioned in other posts, is to use the ChildFragmentManager for the FragmentPagerAdapter, as it updates correctly during the life cycle of the container fragment.
As there are projects (like my current ones) where both options are impossible, I published a solution here that works with an arbitrary FragmentManager using hashCode sub-fragments as the identifier of the fragment element in this position.This is due to the price of storing all fragments for all positions in the adapter.
public class MyPagerAdapter extends FragmentPagerAdapter { private static int COUNT = ...; private final FragmentManager fragmentManager; private Fragment[] subFragments = new Fragment[COUNT]; private FragmentTransaction cleanupTransaction; public MyPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager); this.fragmentManager = fragmentManager; } @Override public Fragment getItem(int position) { return getSubFragmentAtPosition(position); } @Override public int getCount() { return COUNT; } @Override public long getItemId(int position) { return getSubFragmentAtPosition(position).hashCode(); }
}
Nantoka Nov 21 '17 at 10:49 on 2017-11-21 10:49
source share