Fragment 注意事项

一、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。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容