首页 > 解决方案 > 使用 ViewPager 进行屏幕旋转 - FragmentManager 和 FragmentPagerAdapter 的问题

问题描述

我在使用 ViewPager 处理 Fragment 时遇到了一些问题。

我所拥有的:一个包含显示一些片段
的活动(例如, )。其中一些包含一个回调接口,将在. 有一个类,用作. 和一个in来存储一些 Fragment 将显示在.MainActivityViewPagerMainActivity
MainActivityFragmentPagerAdapterViewPagerList<Fragment>FragmentPagerAdapterViewPager

我所期待的:
第一次启动,当我点击其中的一个按钮时,Fragment 调用了回调接口的方法,而 MainActivity 在其中做了一些事情。效果很好。
屏幕旋转后,我希望它的工作方式与第一次启动相同,
NullPointerException:尝试在空引用对象(特别是片段的接口)上调用方法时打到了我的脸。

我所知道
的: -getItem(int position)创建 Fragment 后将不会再次调用。相反,instantiateItem(ViewGroup container, int position)将被调用。
-将在ViewPager 和FragmentManagerFragment 中存储一些 Fragment mActive.mValues
-存储 Fragment 状态的正确方法是什么?(我在 StackOverflow 上也参考了这个和其他一些相同的主题。)

我试过和看到的:
- 覆盖instantiateItem(ViewGroup container, int position)
- 调试了 1 天。我看到当我将getSupportFragmentManager()MainActivity 的onCreate()方法传递给FragmentPagerAdapter' 的超级构造函数时,在第一次启动时,它有一个“内存地址”,假设它是 '1a1a1a1'mActive.mValues保存了一些 Fragment的FragmentManager“内存地址”,它们与List<Fragment>包含它们的内容相同(假设它是 'qwertyu')。这意味着它是正确的。
但是当我旋转屏幕,getSupportFragmentManager()再次传递时,“内存中的地址”完全不同,假设为“9f9f9f9”。并且FragmentManager'mActive.mValues包含一组不同的 Fragment '“内存中的地址”),尽管其中的 Fragment 数量等于第一次启动时(旋转前)保存的 Fragment 数量。
我已经List<Fragment>用一个新的“内存地址”(假设“abababa”)添加了一个片段,具有回调接口。但是当我点击其中的按钮时,它是旋转后在FragmentManager's中的片段(如我上面假设mActive.mValues的那样,“内存中的地址”是'abcdeff'),并且那个没有回调接口(由于没有先设置)。并导致上面提到的NullPointerException 。MainActivity

我现在的问题是:
- 首先,如何摆脱这个问题!?最好继续使用FragmentPagerAdapter而不是另一个类。但我也会考虑使用其他类。
- 第二,你能解释为什么FragmentManager在旋转之前保存 Fragment 实例吗?但是在旋转之后,它会创建一个完全不同的 Fragment 实例,但仍然使用它而不是保存在List<Fragment>?

这是代码(我想我没有instantiateItem(ViewGroup container, int position)以正确的方式使用该方法,所以它仍然导致了问题)。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Attach the SectionsPagerAdapter to the ViewPager
        SectionsPagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
        ViewPager viewPager = findViewById(R.id.viewPager);
        viewPager.setAdapter(pagerAdapter);
    }


    //
    //
    //Adapter class
    private class SectionsPagerAdapter extends FragmentPagerAdapter {
        private static final int PAGE_HOME = 0;
        private int tabCount = 1;
        private List<Fragment> fragmentList = new ArrayList<>();
        private List<String> fragmentTitleList = new ArrayList<>();
        //private FragmentManager fragmentManager;

        SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
            //fragmentManager = fm;

            //Default HomeFragment
            HomeFragment homeFragment = new HomeFragment();
            //Callback interface
            homeFragment.setOnCategoryFragmentChangedListener(new HomeFragment.OnCategoryFragmentChangedListener() {
                //This method will be called when a button in HomeFragment is clicked
                @Override
                public void onAddNewCategory(String categoryName) {
                    addNewCategory(categoryName);
                }
            });
            fragmentList.add(homeFragment);
            fragmentTitleList.add("Home");
        }

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

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

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            fragmentList.set(position, (Fragment) super.instantiateItem(container, position));
            return fragmentList.get(position);
        }

        private void addNewCategory(String categoryName) {
            CategoryFragment fragment = new CategoryFragment();

            tabCount += 1;
            fragmentList.add(fragment);
            fragmentTitleList.add(categoryName);
            notifyDataSetChanged();
        }
    }
}

请帮忙。我已经疯了2天了……!

标签: androidandroid-fragments

解决方案


我相信 android 在方向更改期间会重新启动活动,从而生成多个 FragmentPagerAdapter 实例和多个 List 实例集。

我不完全理解你的问题,但我怀疑 instantiateItem 无论如何都没有做任何事情。不Fragment getItem(int pos)覆盖instanceiteItem() 就不行吗?


推荐阅读