美文网首页AndroidAndroid经验谈
ViewPager中动态更换Fragment不刷新的问题

ViewPager中动态更换Fragment不刷新的问题

作者: 諸星団 | 来源:发表于2016-09-02 16:22 被阅读5656次

    是使用ViewPager+Fragment构建界面的时候,遇到了这样的需求:在ViewPager的第一个item中有一个Button,点击Button会将第一个item中的Fragment换成另外一个Fragment。之前想的是将adapter中List<Fragment>中的数据换掉,然后notifyDataSetChanged,发现无效。研究FragmentPagerAdapter的源码发现,

    @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
    
            final long itemId = getItemId(position);
    
            // Do we already have this fragment?
            String name = makeFragmentName(container.getId(), itemId);
            Fragment fragment = mFragmentManager.findFragmentByTag(name);
            if (fragment != null) {
                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);
            }
    
            return fragment;
        }
    

    其在instantiateItem方法中并不是直接去List里面拿到Fragment的,而是先从FragmentManager中通过Tag找对应的Fragment,如果可以找到就不会去List里面拿了,这样无论再怎么更新list都是没用的,解决思路如下:

    1、在重写instantiateItem方法,手动从FragmentManager将需要更新的Fragment移除,代码如下:

    @Override
        public Object instantiateItem(ViewGroup container, int position) {
            // TODO Auto-generated method stub
            if (position == 0)
                removeFragment(container,position);
            return super.instantiateItem(container, position);
        }
    
        private void removeFragment(ViewGroup container,int index) {
            String tag = getFragmentTag(container.getId(), index);
            Fragment fragment = fm.findFragmentByTag(tag);
            if (fragment == null)
                return;
            FragmentTransaction ft = fm.beginTransaction();
            ft.remove(fragment);
            ft.commit();
            ft = null;
            fm.executePendingTransactions();
        }
    

    由于我这里要动态更换的是第一个item的fragment,所以就直接做判断if (position == 0),其他情况可以按需修改。首先通过一个getFragmentTag方法得到当前position的fragment的tag,这个方法里面其实就是用反射的方式调用了FragmentPagerAdapter的makeFragmentName方法,因为这里的tag是在这个方法中计算出来的,此段代码如下:

    private String getFragmentTag(int viewId, int index) {  
            try {  
                Class<FragmentPagerAdapter> cls = FragmentPagerAdapter.class;  
                Class<?>[] parameterTypes = { int.class, long.class };  
                Method method = cls.getDeclaredMethod("makeFragmentName",  
                        parameterTypes);  
                method.setAccessible(true);  
                String tag = (String) method.invoke(this, viewId, index);  
                return tag;  
            } catch (Exception e) {  
                e.printStackTrace();  
                return "";  
            }  
        }  
    

    得到Tag后就可以通过FragmentManager的findFragmentByTag方法得到fragment,如果存在,就通过FragmentTransaction 移除掉即可。

    最后重写getItemPosition() 方法,返回 POSITION_NONE。代码如下:

    @Override  
        public int getItemPosition(Object object) {  
            // TODO Auto-generated method stub  
            return POSITION_NONE;  
        }  
    

    2、使用FragmentStatePagerAdapter,它不会对fragment做缓存,每次都会销毁重建,这样效率很低,只适合页面非常少访问不频繁等特殊情况。

    相关文章

      网友评论

      • Bury丶冬天:并没有什么卵用
      • b4edba7f37e0:感谢大神分享, 解决了我的问题
      • 8289ff4b3b7b:找了各种方法,终于解决了,谢了:+1:
      • 83c3cbb5a86a:感谢楼主,找了一天终于解决了,谢谢
      • 宝塔山上的猫:感谢帮助,刚好遇到这个问题,看了很多资料不会解决~~~
        然后我选择把所有fragment销毁:joy:
        虽然问题解决了,但是完全没效率········
        諸星団: @宝塔山上的猫 不客气,希望能解决你的问题(⁄ ⁄•⁄ω⁄•⁄ ⁄)

      本文标题:ViewPager中动态更换Fragment不刷新的问题

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