美文网首页四大组件
ViewPager中Fragment 刷新问题

ViewPager中Fragment 刷新问题

作者: Fitz_e74a | 来源:发表于2019-05-24 15:22 被阅读45次

    项目需求,如下图


    17916601-73a444836e4089ed.jpg

    实现方法

    主MainActivity 承载5个fragment,对应着下面5个按钮进行切换,该处使用的fragment的add与hide方法同时加载,调用方法如下:

       private void showFragment(Fragment targetFragment) {
            //如果当前fragment和目标fragment一致
            if (targetFragment == currentFragment) {
                return;
            }
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            if (currentFragment != null) {
                ft.hide(currentFragment);
            }
            if (targetFragment.isAdded()) {
                //如果目标已被添加,直接显示即可
                ft.show(targetFragment);
            } else {
                //如果未被添加,则需添加后显示
                ft.add(R.id.framelayout, targetFragment).show(targetFragment);
            }
            ft.commitAllowingStateLoss();
            currentFragment = targetFragment;
        }
    

    而首页界面对应的是多个不同tab,用ViewPager 承载fragment进行实现,开始的时候使用原始FragmentPagerAdapter,只重写了

        @Override
        public Fragment getItem(int i) {
            return mFragmentList.get(i);
        }
    
        @Override
        public int getCount() {
            return mFragmentList == null ? 0 : mFragmentList.size();
        }
    
    

    并在首页fragment创建的时候调用

            mHomePagerAdapter = new FragmentAdapter(getChildFragmentManager(), mFragmentList);
            viewPager.setAdapter(mHomePagerAdapter);
            viewPager.setCurrentItem(0);
            magicIndicator.onPageSelected(0);
    

    收到数据回调的时候,重新如下处理:

        @Override
        public void getUserTypesSuccess(List<TemplateTypeModel> list) {
            mTemplateTypeModels = list;
            Collections.sort(mTemplateTypeModels, (o1, o2) -> o1.getTypeOrder() - o2.getTypeOrder());
            mCommonNavigatorAdapter.notifyDataSetChanged();
            if (mFragmentList == null) mFragmentList = new ArrayList<>();
            mFragmentList.clear();
            for (TemplateTypeModel model : list) {
                mFragmentList.add(TypeListFragment.newInstance(model));
            }
        mHomePagerAdapter.notifyDataSetChanged();
        }
    
    

    问题

    界面未收到刷新(这里有个注意点,在fragment里承载viewpager要使用getChildFragmentManager)

    修改方式:

    怀疑为缓存问题,实际也正是viewpager缓存问题
    尝试拿到数据,重新设置adapter

      @Override
        public void getUserTypesSuccess(List<TemplateTypeModel> list) {
            mTemplateTypeModels = list;
            Collections.sort(mTemplateTypeModels, (o1, o2) -> o1.getTypeOrder() - o2.getTypeOrder());
            mCommonNavigatorAdapter.notifyDataSetChanged();
            if (mFragmentList == null) mFragmentList = new ArrayList<>();
            mFragmentList.clear();
            for (TemplateTypeModel model : list) {
                mFragmentList.add(TypeListFragment.newInstance(model));
            }
            mHomePagerAdapter = new FragmentAdapter(getChildFragmentManager(), mFragmentList);
            viewPager.setAdapter(mHomePagerAdapter);
            viewPager.setCurrentItem(0);
            magicIndicator.onPageSelected(0);
        }
    
    

    问题

    运行发现更新的时候,可以正常更新数据,等等,增删list 数量的时候,发现viewpager中fragment 展示的界面和实际期望的界面不一样,莫非还是缓存问题,上网经过一番,需要设置adapter 中

        @Override
        public int getItemPosition(@NonNull Object object) {
            return POSITION_NONE;
        }
    

    修改

    加入之后,发现效果不明显,继续百度,有人说要删除fragmentmanager中的fragment,好吧,加入,看一下,继续修改

       @Override
        public void getUserTypesSuccess(List<TemplateTypeModel> list) {
            List<Fragment> olds = getChildFragmentManager().getFragments();
            if (olds != null) {
                FragmentTransaction ft = getChildFragmentManager().beginTransaction();//获得FragmentTransaction 事务
                for (Fragment f : olds) {
                    ft.remove(f); //遍历删除fragment
                }
                ft.commit();
                getChildFragmentManager().executePendingTransactions();
            }
            mTemplateTypeModels = list;
            Collections.sort(mTemplateTypeModels, (o1, o2) -> o1.getTypeOrder() - o2.getTypeOrder());
            mCommonNavigatorAdapter.notifyDataSetChanged();
            if (mFragmentList == null) mFragmentList = new ArrayList<>();
            mFragmentList.clear();
            for (TemplateTypeModel model : list) {
                mFragmentList.add(TypeListFragment.newInstance(model));
            }
            mHomePagerAdapter = new FragmentAdapter(getChildFragmentManager(), mFragmentList);
            viewPager.setAdapter(mHomePagerAdapter);
            viewPager.setCurrentItem(0);
            magicIndicator.onPageSelected(0);
        }
    

    运行,完美解决问题,不过总感觉不够优雅

    使用FragmentStatePagerAdapter

    由于FragmentPagerAdapter和FragmentStatePagerAdapter内部缓存机制不一样,FragmentStatePagerAdapter是直接销毁fragment,而不是复用,具体区别可以参考 FragmentPagerAdapter与FragmentStatePagerAdapter区别

            viewPager.setAdapter(mHomePagerAdapter = new FragmentStatePagerAdapter(getChildFragmentManager()) {
                @Override
                public int getCount() {
                    return mFragmentList == null ? 0 : mFragmentList.size();
                }
    
                @Override
                public Fragment getItem(int i) {
                    return mFragmentList.get(i);
                }
    
    
                @Override
                public int getItemPosition(@NonNull Object object) {
                    return POSITION_NONE;
                }
            });
    

    这里可以直接使用notifyDataSetChanged进行界面的刷新

      @Override
        public void getUserTypesSuccess(List<TemplateTypeModel> list) {
    
            mTemplateTypeModels = list;
            Collections.sort(mTemplateTypeModels, (o1, o2) -> o1.getTypeOrder() - o2.getTypeOrder());
            mCommonNavigatorAdapter.notifyDataSetChanged();
            if (mFragmentList == null) mFragmentList = new ArrayList<>();
            mFragmentList.clear();
            for (TemplateTypeModel model : list) {
                mFragmentList.add(TypeListFragment.newInstance(model));
            }
            mHomePagerAdapter.notifyDataSetChanged();
            viewPager.setCurrentItem(0);
            magicIndicator.onPageSelected(0);
        }
    
    

    总结:

    遇到viewpager 使用fragment,界面不刷新的问题,可以考虑使用FragmentStatePagerAdapter,并重写

          @Override
                public int getItemPosition(@NonNull Object object) {
                    return POSITION_NONE;
                }
    

    然后就和使用listview等数据刷新行为一致了

    相关文章

      网友评论

        本文标题:ViewPager中Fragment 刷新问题

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