美文网首页
Fragment 注意事项

Fragment 注意事项

作者: 一方乌鸦 | 来源:发表于2020-04-11 11:00 被阅读0次

    一、FragmentPagerAdapter 和 FragmentPagerStateAdapter

    1. 区别

    setOffScreenPageLimit(int limit)设置viewpager左右预加载页,
    FragmentPagerAdapter将每一个生成的Fragment保存在内存中,limit外的Fragment一旦初始化后就不销毁。
    FragmentStatePagerAdapter对limit外的Fragment销毁。

    使用场景:
    对于固定较少数量的页面使用FragmentPagerAdapter,如引导页,Tab页面;
    对于拥有大量页面的情况应使用FragmentStatePagerAdapter避免占用大量内存,如图片预览

    2. Fragment引用

    不应该在Activity的成员变量中实例化 Fragment 或实例化 List<Fragment> 去存储 Fragment。原因涉及到Fragment的保存与恢复,下面会分析。
    如果需要获取到 Fragment,则需要使用如下结构:

    public class MyPagerAdapter extends FragmentStatePagerAdapter {
        SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        @Override
        public int getCount() {
            return ...;
        }
        @Override
        public Fragment getItem(int position) {
            return MyFragment.newInstance(...); 
        }
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment fragment = (Fragment) super.instantiateItem(container, position);
            registeredFragments.put(position, fragment);
            return fragment;
        }
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            registeredFragments.remove(position);
            super.destroyItem(container, position, object);
        }
        public Fragment getRegisteredFragment(int position) {
            return registeredFragments.get(position);
        }
    }
    

    二、Fragment 状态保存与恢复

    Fragmentde 的保存与恢复涉及到 FragmentManagerImpl中的两个方法 saveAllState和restoreAllState。
    当Activity触发onSaveInstanceState时,会将 Fragmentmanager的mAdded、mActive数组中的Fragment转化成FragmentState,而FragmentState是一个Parcel,可以被存到Activity的Bundle中,等到Activity再次onCreate时,会将已保存在Bundle中的FragmentState再恢复出来,转化成FragmentManager的mAdded,mActive。
    FragmentManager帮我们做了所有的保存与恢复的工作,如果我们在Activity中重新创建Fragment,那么这些在Activity中创建的Fragment可能并不是FragmentManager的Fragment。

    下面写个例子

    public class DemoActivity extends FragmentActivity {
        private List<Fragment> fragments = new ArrayList<>();
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            FragmentManager fm = getSupportFragmentManager();
            fragments.add(DemoFragment.newInstance(0));
            fragments.add(DemoFragment.newInstance(1));
            fragments.add(DemoFragment.newInstance(2));
            final Adapter adapter = new Adapter(fragments, fm);
            vp.setAdapter(adapter);
            vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            ...
                @Override
                public void onPageSelected(int i) {
                    Log.d(TAG, String.valueOf(adapter.array.get(i) == adapter.fragments.get(i)));
                }
            });
        }
    }
    
    static class Adapter extends FragmentPagerAdapter {
        Adapter(List<Fragment> fragments, FragmentManager fm) {
            super(fm);
            this.fragments = fragments;
        }
        List<Fragment> fragments;
        SparseArray<Fragment> array = new SparseArray<>();
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            Fragment fragment = (Fragment) super.instantiateItem(container, position);
            array.put(position, fragment);
            return fragment;
        }
        @Override
        public Fragment getItem(int i) {
            return fragments.get(i);
        }
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            array.delete(position);
            super.destroyItem(container, position, object);
        }
        @Override
        public int getCount() {
            return 3;
        }
    }
    

    上面的代码在Adapter中 保存了两个关于Fragment的集合,其中fragment是Activity创建的,array存的是每次PagerAdapter执行instantiateItem创建的Fragment。
    需要验证的是,当Activity被重建的时候(通过开发者选项不保留活动),两个Fragment集合是一样的吗?答案在 onPageSelected中。
    当每次在滑动的时候,onPageSelected 中的 Log 打印的是什么呢?答案是 false。

    相关文章

      网友评论

          本文标题:Fragment 注意事项

          本文链接:https://www.haomeiwen.com/subject/jebqmhtx.html