• 动态更新ViewPager中的Fragment(替换Fragment)


    1.最近做需求,遇到一个问题,一个Fragment中包含了一个ViewPager,viewPager中包含一adapter ,adapter中包含了4个Fragment。想要动态替换第3个Fragment由A Fragment--》B Fragment。如图:

    2. 原本以为很简单的事,分分钟就能搞定,但是更新了list<Fragment> 数据源,notifyDataSetChanged()后,页面没有被替换,邪门啊。

    3.上网一通乱查,发现一个说法:重写getItemPosition()方法返回POSITION_NONE 进行刷新。于是乎,查了下源码,大致刷新的过程,如图:

    4.流程知道了,具体怎么实现呢。从无到有是最难的,还是参考下系统类吧:FragmentPagerAdapter ,把它重写。见代码

    public class TabFragmentAdapter extends PagerAdapter {
        private static final String TAG = "FragmentPagerAdapter";
        private static final boolean DEBUG = false;
    
        private FragmentManager mFragmentManager;
        private FragmentTransaction mCurTransaction = null;
        private Fragment mCurrentPrimaryItem = null;
    
        private boolean isRefesh = false;
        ArrayList<Fragment> list = new ArrayList<>();
        //刷新对象的接口
        public interface RefeshFragment{
    
        }
    
        public boolean isRefesh(Object object) {
            if (isRefesh && (object instanceof RefeshFragment)) {
                return true;
            } else {
                return false;
            }
        }
    
        public void setRefesh(boolean t) {
            isRefesh = t;
        }
    
        public TabFragmentAdapter(FragmentManager fm) {
            mFragmentManager = fm;
        }
    
        public void setFragments(ArrayList fragments) {
            if (this.list != null) {
                this.list = fragments;
            }
        }
    
        public Fragment getItem(int position) {
            return list.get(position);
        }
    
        @Override
        public int getCount() {
            return list == null ? 0 : list.size();
        }
    
        @SuppressWarnings("ReferenceEquality")
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
    
            final long itemId = getItemId(position);
    
            String name = makeFragmentName(container.getId(), itemId);
            Fragment fragment = mFragmentManager.findFragmentByTag(name);
            if (fragment != null && !(isRefesh(fragment))) {
                if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
                mCurTransaction.attach(fragment);
            } else {
                fragment = getItem(position);
                if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
                mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));
            }
            if (fragment != mCurrentPrimaryItem) {
                fragment.setMenuVisibility(false);
                fragment.setUserVisibleHint(false);
            }
    
            if (isRefesh(fragment)) {
                isRefesh = false;
            }
            return fragment;
        }
    
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            if (mCurTransaction == null || isRefesh(object)) {//避免缓存指令的干扰 每次使用新的 BackStackRecord 对象
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            if (DEBUG)
                Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object + " v=" + ((Fragment) object).getView());
            if (isRefesh(object)) {
                mCurTransaction.remove((Fragment) object);
            } else {
                mCurTransaction.detach((Fragment) object);
            }
        }
    
        @SuppressWarnings("ReferenceEquality")
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            Fragment fragment = (Fragment) object;
            if (fragment != mCurrentPrimaryItem) {
                if (mCurrentPrimaryItem != null) {
                    mCurrentPrimaryItem.setMenuVisibility(false);
                    mCurrentPrimaryItem.setUserVisibleHint(false);
                }
                if (fragment != null) {
                    fragment.setMenuVisibility(true);
                    fragment.setUserVisibleHint(true);
                }
                mCurrentPrimaryItem = fragment;
            }
        }
    
        @Override
        public void finishUpdate(ViewGroup container) {
            if (mCurTransaction != null) {
                mCurTransaction.commitAllowingStateLoss();
                mCurTransaction = null;
            }
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return ((Fragment) object).getView() == view;
        }
    
        @Override
        public Parcelable saveState() {
            return null;
        }
    
        @Override
        public void restoreState(Parcelable state, ClassLoader loader) {
        }
    
    
        public long getItemId(int position) {
            return position;
        }
    
        private static String makeFragmentName(int viewId, long id) {
            return "android:switcher:" + viewId + ":" + id;
        }
    
    
        @Override
        public int getItemPosition(Object object) {
            if (isRefesh(object)) {//是否进行销毁
                return POSITION_NONE;
            } else {
                return POSITION_UNCHANGED;
            }
    
        }
    }

    5.说明:

    a.你要替换的Fragment需要先实现空接口RefeshFragmnet,用来表明你是需要被替换的。

    b.调用时

               mFragmentList.set(FRAGMENT_STOCKS,new StocksFragment());//替换数据源
               adapter.setRefesh(true);//设置刷新标识
               adapter.notifyDataSetChanged();//通知adapter刷新

    6.小结:其实adapter的源码挺简单的,viewPager比较复杂。只要有耐心,跟着源码debug,为之,则难者亦易矣。上边的代码要是有不懂的地方可以在下方留言或者debug一下

  • 相关阅读:
    Filebeats input多个log文件,输出Kafka多个topic配置
    CentOS7 yum方式安装MySQL5.7
    day11笔记用户管理篇
    RT1021之LED小灯闪烁(EVK)
    TSN介绍
    vba获取文件夹下所有文件名
    Win7系统安装JDK后javac不是内部或外部命令解决办法
    nodejs&wsl&vscode&docker开发环境搭建
    Java应用层数据链路追踪(附优雅打印日志姿势)
    SpringBoot接入轻量级分布式日志框架(GrayLog)
  • 原文地址:https://www.cnblogs.com/androiddream/p/9318684.html
Copyright © 2020-2023  润新知