Fragment view in ViewPager is not restored when resuming

前端 未结 6 1415
独厮守ぢ
独厮守ぢ 2020-11-30 12:23

I have ActionBar Tabs setup. It consists of 4 tabs. Everything is fine until I navigate away from TabbedFragment and returning back.

I create tabs like

相关标签:
6条回答
  • 2020-11-30 12:42

    Or more simply when navigating back to tabbedfragment (assuming you use an intent and the fragment is within an activity) use:

    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    

    This keeps the original activity and moves it to the top of the stack rather than recreating it, thus you never need to recreate the viewPager.

    0 讨论(0)
  • 2020-11-30 12:43

    The problem exists in the Fragments you use as tabs, I think. They seem to not show anything when they are resumed (see Fragment lifecycle). The "weird" issue that only the currently selected +/-1 tab is empty, is because the offScreenPageLimit of your ViewPager is 1 by default. All tabs above this threshold are re-created.

    Therefore, increasing the value will -- in your case -- cause all your tabs to appear empty after resuming. Check in your Fragment code which lifecycle methods you use to inflate your layout, set adapters and so forth, because that's what's causing your trouble.

    0 讨论(0)
  • 2020-11-30 12:51

    Okay so When using a FragmentStatePagerAdapter your fragments will be destroyed when you navigate anymore than one fragment Away since by default offScreenPageLimit is set to 1 by default just as mentioned above.

    Typically this Class is used for an activity that has a very large set of Fragments, i.e have to scroll through a large amount of views. If your application does not need more than say 3-4 tabs I would suggest using FragmentPagerAdapter instead, and then specifying your offScreenPageLimit to something like 3, so if you get to the 4th Tab, all 3 tabs before will still be in memory.

    Here is some Sample Code for a project on github that i created illustrating how to dynamically load the fragments if you don't want to add this offScreenPageLimit.

    https://github.com/lt-tibs1984/InterfaceDemo/blob/master/src/com/divshark/interfacedemo/InterfaceDemoMain.java

    Walk through all this code in this Class, and you will see how I'm dynamically loading the fragments, each time my ViewPager is slid over. Most notably at the bottom.

    You can download this code, and use it as a test base for what you want to do. Try adding the setOffScreenPageLimit(2) in the onCreate() method for the viewPager and notice the different behavior. To check the behavior, edit the text in fragment 1. Navigate Away and navigate back, with this set or not. You will see when it is set, the fragment's text remains what you change it to, since the fragment is never recreated.

    Please provide additional questions if you have them.

    GoodLuck

    UPDATE

    private static final String [] fragmentClasses = {"com.example.project.YourFragment1","com.example.project.YourFragment2","com.example.project.YourFragment3"};
    
    
    
     viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {
    
        @Override
        public Fragment getItem(int position) {
    
           Fragment fragmentAtPosition = null;
    
           // $$$$ This is the Important Part $$$$$
           // Check to make sure that your array is not null, size is greater than 0 , current position is greater than equal to 0, and position is less than length
           if((fragmentClasses != null) && (fragmentClasses.length > 0)&&(position >= 0)&& (position < fragmentClasses.length))
            {
           // Instantiate the Fragment at the current position of the Adapter
            fragmentAtPosition = Fragment.instantiate(getBaseContext(), fragmentClasses[position]);
            fragmentAtPosition.setRetainInstance(true);
    
           }
    
            return fragmentAtPosition;
        }
    
        @Override
        public int getCount() {
            return fragmentClasses.length;
        }
    });
    
    0 讨论(0)
  • 2020-11-30 12:54

    After a while ran into the same problem again, so updating this question. If you're using FragmentStatePagerAdapter you should provide FragmentManager via getChildFragmentManager() instead of getFragmentManager(). See Issue 55068: ViewPager doesn't refresh child fragments when back navigation via backstack

    0 讨论(0)
  • 2020-11-30 12:59

    After doing much research, this worked for me. I have a complex layout with 3 tabs in a fragment, that gets switched out for other fragments. I realized that the ViewpagerAdapter will retain state, even if you press the home button. My problem was switching back and forth would null out the child fragment UI view elements and crash. The key is to not new out your ViewPagerAdapter. Adding the null check for the Adapter worked for me. Also, be sure to allocate setOffscreenPageLimit() for your needs. Also, from what I understand setRetainInstance(true); should not be used for fragments that have UI, it is designed for headless fragments.

    In the fragment that holds your Tabs:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_tab, container, false);
        tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
        viewPager = (ViewPager) view.findViewById(R.id.viewPager);
    
        //Important!!! Do not fire the existing adapter!!
        if (viewPagerAdapter == null) {
            viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
            viewPagerAdapter.addFragments(new AFragment(), "A");
            viewPagerAdapter.addFragments(new BFragment(), "B");
            viewPagerAdapter.addFragments(new CFragment(), "C");
        }
        //Allocate retention buffers for three tabs, mandatory
        viewPager.setOffscreenPageLimit(3);
        tabLayout.setupWithViewPager(viewPager);
        viewPager.setAdapter(viewPagerAdapter);
    
        return view;
    }
    
    0 讨论(0)
  • 2020-11-30 13:03

    I guess this happens because while loading fragment android loads current and current+1, if you debug you would not see onPause getting called for the immediate next fragment.

    You can reload content programmatically in onTabChanged() method of TabHost.OnTabChangeListener.

    0 讨论(0)
提交回复
热议问题