ViewPager and fragments — what's the right way to store fragment's state?

后端 未结 11 1326
遇见更好的自我
遇见更好的自我 2020-11-22 02:21

Fragments seem to be very nice for separation of UI logic into some modules. But along with ViewPager its lifecycle is still misty to me. So Guru thoughts are b

11条回答
  •  借酒劲吻你
    2020-11-22 02:28

    I want to offer an alternate solution for perhaps a slightly different case, since many of my searches for answers kept leading me to this thread.

    My case - I'm creating/adding pages dynamically and sliding them into a ViewPager, but when rotated (onConfigurationChange) I end up with a new page because of course OnCreate is called again. But I want to keep reference to all the pages that were created prior to the rotation.

    Problem - I don't have unique identifiers for each fragment I create, so the only way to reference was to somehow store references in an Array to be restored after the rotation/configuration change.

    Workaround - The key concept was to have the Activity (which displays the Fragments) also manage the array of references to existing Fragments, since this activity can utilize Bundles in onSaveInstanceState

    public class MainActivity extends FragmentActivity
    

    So within this Activity, I declare a private member to track the open pages

    private List retainedPages = new ArrayList();
    

    This is updated everytime onSaveInstanceState is called and restored in onCreate

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        retainedPages = _adapter.exportList();
        outState.putSerializable("retainedPages", (Serializable) retainedPages);
        super.onSaveInstanceState(outState);
    }
    

    ...so once it's stored, it can be retrieved...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        if (savedInstanceState != null) {
            retainedPages = (List) savedInstanceState.getSerializable("retainedPages");
        }
        _mViewPager = (CustomViewPager) findViewById(R.id.viewPager);
        _adapter = new ViewPagerAdapter(getApplicationContext(), getSupportFragmentManager());
        if (retainedPages.size() > 0) {
            _adapter.importList(retainedPages);
        }
        _mViewPager.setAdapter(_adapter);
        _mViewPager.setCurrentItem(_adapter.getCount()-1);
    }
    

    These were the necessary changes to the main activity, and so I needed the members and methods within my FragmentPagerAdapter for this to work, so within

    public class ViewPagerAdapter extends FragmentPagerAdapter
    

    an identical construct (as shown above in MainActivity )

    private List _pages = new ArrayList();
    

    and this syncing (as used above in onSaveInstanceState) is supported specifically by the methods

    public List exportList() {
        return _pages;
    }
    
    public void importList(List savedPages) {
        _pages = savedPages;
    }
    

    And then finally, in the fragment class

    public class CustomFragment extends Fragment
    

    in order for all this to work, there were two changes, first

    public class CustomFragment extends Fragment implements Serializable
    

    and then adding this to onCreate so Fragments aren't destroyed

    setRetainInstance(true);
    

    I'm still in the process of wrapping my head around Fragments and Android life cycle, so caveat here is there may be redundancies/inefficiencies in this method. But it works for me and I hope might be helpful for others with cases similar to mine.

提交回复
热议问题