简体   繁体   English

在屏幕旋转时在 ViewPager 中保存片段状态

[英]Save fragments state in ViewPager on screen rotation

I have TabLayout and ViewPager with 2 fragments, each of them is a recyclerView that load data from firebase.我有带有 2 个片段的 TabLayout 和 ViewPager,每个片段都是一个从 firebase 加载数据的 recyclerView。

All works fine.一切正常。 But when I change screen orientation ViewPager recreate each fragment and fragments load data again.但是当我改变屏幕方向 ViewPager 重新创建每个片段和片段再次加载数据。

Is it possible and how to save fragment state in ViewPager?是否有可能以及如何在 ViewPager 中保存片段状态?

But I do not want to override onSaveInstanceState method for creating data set and then restore it.但我不想覆盖 onSaveInstanceState 方法来创建数据集然后恢复它。 I want something like find fragment by tag when check existing fragment.我想要在检查现有片段时按标签查找片段之类的东西。

Activity活动

public class MainActivity extends BaseBroadcastActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    mViewPager = (ViewPager) findViewById(R.id.viewpager);
    setupViewPager(mViewPager);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);
}

private void setupViewPager(ViewPager viewPager) {
    Adapter adapter = new Adapter(getSupportFragmentManager());
    adapter.addFragment(MainListFragment.newInstance(connected, "Notices"), "Notices");
    adapter.addFragment(MainListFragment.newInstance(connected, "Posts"), "Posts");
    viewPager.setAdapter(adapter);
}

static class Adapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragments = new ArrayList<>();
    private final List<String> mFragmentTitles = new ArrayList<>();

    public Adapter(FragmentManager fm) {
        super(fm);
    }

    public void addFragment(Fragment fragment, String title) {
        mFragments.add(fragment);
        mFragmentTitles.add(title);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitles.get(position);
    }
}

In MainListFragment I only create recyclerView and load data from firebase.在 MainListFragment 中,我只创建 recyclerView 并从 firebase 加载数据。

Thank You!谢谢你!

EDIT编辑

Thank You for responding!感谢您的回复!

I find my error.我发现我的错误。 What's happen when we create FragmentPageAdapter at first time and when we recreate activity:当我们第一次创建 FragmentPageAdapter 以及重新创建活动时会发生什么:

  1. FragmentPageAdapter call instantiateItem method where it find fragment by tag and if fragment exists adapter use it, but if fragment does not exist adapter call getItem method and create fragment. FragmentPageAdapter 调用 instantiateItem 方法,它按标签查找片段,如果片段存在适配器使用它,但如果片段不存在适配器调用 getItem 方法并创建片段。

  2. In my situation fragments are not recreated, but data is refreshing because I refresh them in onCreateView method in fragment, but now I am edit onCreateView:在我的情况下,片段没有重新创建,但数据正在刷新,因为我在片段的 onCreateView 方法中刷新它们,但现在我正在编辑 onCreateView:

    if (savedInstanceState == null) { retrieveData(); if (savedInstanceState == null) {retrieveData(); } }

It should be done in the way that you return new instance always in getItem() .它应该以您始终在getItem()返回新实例的方式完成。 I would also rather use FragmentStatePagerAdapter especially when you have more pages.我也宁愿使用FragmentStatePagerAdapter尤其是当您有更多页面时。 You also need to save every internal state that can be lost in onSaveInstanceState() .您还需要保存在onSaveInstanceState()可能丢失的每个内部状态。 If you don't want to reload, you'll need to save the data.如果您不想重新加载,则需要保存数据。 If you have some data in POJOs, you can add Serializable interface to them to serialize them easily into bundle.如果您在 POJO 中有一些数据,您可以向它们添加Serializable接口,以便轻松地将它们序列化为 bundle。

There is also setRetainInstance() on fragment, but it always caused some weird behavior for me, so I'm not using it.片段上也有setRetainInstance() ,但它总是给我带来一些奇怪的行为,所以我没有使用它。

static class Adapter extends FragmentStatePagerAdapter {

    public Adapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment=null;
        switch (position) {
            case 0: fragment=MainListFragment.newInstance(mConnected, "Notices"); //don't forget to save mConnected in savedInstanceState
            case 1: fragment=MainListFragment.newInstance(mConnected, "Posts");
        }
        return fragment;
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        String title="";
        switch (position) {
            case 0: title="Notices";
            case 1: title="Posts";
        }
        return title;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM