关于ViewPager清除已加载Fragment,重新创建新的Fragment的方法

7 篇文章 0 订阅
4 篇文章 0 订阅

最近在项目中使用ViewPager+Fragment实现左右两个滑动切换界面。但是遇到一个问题:在不退出当前Activity的情况下,重新加载Fragment,却得到了空白界面,并没有生成新的Fragment添加进去。

这个问题可能是由于旧的Fragment没有被清除导致的。

查看了 FragmentPagerAdapter 类的创建实例的函数 instantiateItem :

@NonNull
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (this.mCurTransaction == null) {
            this.mCurTransaction = this.mFragmentManager.beginTransaction();
        }

        long itemId = this.getItemId(position);
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = this.mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            this.mCurTransaction.attach(fragment);
        } else {
            fragment = this.getItem(position);
            this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));
        }

        if (fragment != this.mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }

        return fragment;
    }

我们看到这个函数会先检查是否已经存在了这样一个Fragment,如果不存在才会去调用 getItem 方法产生一个新的Fragment。所以我们可以利用类似的方法先去FragmentManager中清除对应的Fragment,然后再让适配器重新加载新Fragment。如下我们重写 FragmentPagerAdapter 类:

public class ViewMaterialFragmentPagerAdapter extends FragmentPagerAdapter {

    private FragmentManager mFragmentManager;
    private FragmentTransaction mCurTransaction;
    private Context mContext;
    private List<Fragment> mFragmentArrayList;
    private int[] pagerTitles = new int[]{R.string.text_material_qr_code, R.string.text_material_list};


    public ViewMaterialFragmentPagerAdapter(FragmentManager fm, Context ctx, List<Fragment> fragments) {
        super(fm);
        mFragmentManager = fm;
        mContext = ctx;
        mFragmentArrayList = fragments;
    }


    @Override
    public Fragment getItem(int i) {
        return mFragmentArrayList.get(i);
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mContext.getString(pagerTitles[position]);
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        return super.instantiateItem(container, position);
    }

    /**
     * 清除缓存fragment
     * @param container ViewPager
     */
    public void clear(ViewGroup container){
        if (this.mCurTransaction == null) {
            this.mCurTransaction = this.mFragmentManager.beginTransaction();
        }

        for(int i=0;i<mFragmentArrayList.size();i++){
            long itemId = this.getItemId(i);
            String name = makeFragmentName(container.getId(), itemId);
            Fragment fragment = this.mFragmentManager.findFragmentByTag(name);
            if(fragment != null){//根据对应的ID,找到fragment,删除
                mCurTransaction.remove(fragment);
            }
        }
        mCurTransaction.commitNowAllowingStateLoss();
    }

    /**
     * 等同于FragmentPagerAdapter的makeFragmentName方法,
     * 由于父类的该方法是私有的,所以在此重新定义
     * @param viewId
     * @param id
     * @return
     */
    private static String makeFragmentName(int viewId, long id) {
        return "android:switcher:" + viewId + ":" + id;
    }
}

代码重点是 clear 方法,只要在需要销毁已经加载过得Fragment的地方,调用这个clear方法,再让ViewPager重新设置适配器即可。

pagerAdapter.clear(mViewPager);

mViewPager.setAdapter(pagerAdapter);

clear 方法中的 makeFragmentName 方法,可以在 FragmentPagerAdapter 类源码中找到,此处的makeFragmentName与源码中一模一样,只是由于这个方法在源码中私有的,我就暂且复制过来使用吧,当然也可以使用反射调用。

 

############ 好了,调大音量,听首歌吧 ~ ###############

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值