详解ViewPager调用FragmentPagerAdapter.notifyDataSetChanged()不能更新Fragment

第一部分:现象出现的原因

代码默认实现如此。
FragmentPagerAdapter调用notifyDataSetChanged后,执行mObservable.notifyChanged()。mObservable对象的初始化,是在ViewPager调用setAdapter时被赋值的,对应的类叫PagerObserver。PagerObserver的dataSetChanged方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
for ( int i = 0 ; i < mItems.size(); i++) {
             final ItemInfo ii = mItems.get(i);
             final int newPos = mAdapter.getItemPosition(ii.object);
 
             if (newPos == PagerAdapter.POSITION_UNCHANGED) {
                 continue ;
             }
 
             if (newPos == PagerAdapter.POSITION_NONE) {
                 mItems.remove(i);
                 i--;
 
                 if (!isUpdating) {
                     mAdapter.startUpdate( this );
                     isUpdating = true ;
                 }
 
                 mAdapter.destroyItem( this , ii.position, ii.object);
                 needPopulate = true ;
 
                 if (mCurItem == ii.position) {
                     // Keep the current item in the valid range
                     newCurrItem = Math.max( 0 , Math.min(mCurItem, adapterCount - 1 ));
                     needPopulate = true ;
                 }
                 continue ;
             }
 
             if (ii.position != newPos) {
                 if (ii.position == mCurItem) {
                     // Our current item changed position. Follow it.
                     newCurrItem = newPos;
                 }
 
                 ii.position = newPos;
                 needPopulate = true ;
             }
         }

PagerAdapter的默认getItemPosition实现是 return POSITION_UNCHANGED。所以调用notifyDataSetChanged方法不会刷新Fragment。

第二部分:解决办法

为了让Fragment重新绘制,必须重载FragmentPagerAdapter的getItemPositon方法并修改为return POSITION_NONE。这样之前所有的Fragment都会被detach掉。

1
2
3
4
@Override
     public int getItemPosition(Object object) {
         return POSITION_NONE;
     }

如果你按上面的步骤做了,而且调用notifyDataSetChanged时候,list数据位空,那么结果是你希望看到的。但是如果list的数据在原有的基础上做了修改,但是结果你看到的Fragment上显示的信息还是之前的数据。

第三部分:Fragment不刷新的原因

如第二部分描述,旧的Fragment都会被detach掉,但是它并没有被distory掉,而是被保存下来了,保存时候存储的tag来源如下代码:

1
2
3
private static String makeFragmentName( int viewId, long id) {
         return "android:switcher:" + viewId + ":" + id;
     }

刷新后调用FragmentPagerAdapgter的instantiateItem方法,会通过findFragmentByTag找到被detach掉的Fragment,然后再执行该Fragemnt的attach方法,最后再次执行Fragment的生命周期,所以你看到的Fragment上面的数据还是老数据。

第四部分:解决办法

如第三部分描述,如果Fragment你是通过getItem方法中去new一个Fragment出来,然后数据通过setArgument设置进去的。那么再次执行改Fragment的attach方法后,拿到的数据还是老数据。解决版本就是在instantiateItem方法中调用Fragment的自定义方法resetFragmentData(),把旧数据替换掉。注:resetFragmentData只能做数据替换,不能直接更新view,View的更新还是在调用attach方法后继续执行到onActivityCreated方法后执行刷新View。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class CarTypeListAdapter extends FragmentPagerAdapter {
 
     private final ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> mRecList;
     protected ImageWorker mImageFetcher;
 
     public CarTypeListAdapter(FragmentManager fm, ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> recList, ImageWorker worker) {
         super (fm);
         this .mRecList = recList;
         this .mImageFetcher = worker;
     }
 
     @Override
     public Fragment getItem( int position) {
         CarTypeInfoFragment imageFragment = CarTypeInfoFragment.newInstance(mRecList.get(position), mImageFetcher);
         return imageFragment;
     }
 
     public Object instantiateItem(ViewGroup container, int position) {
         CarTypeInfoFragment f = (CarTypeInfoFragment) super .instantiateItem(container, position);
         if (!QArrays.isEmpty(mRecList) && position >= 0 && position < mRecList.size()){
             CarTypeListMinPriceResult.CarTypeMinPrice p = mRecList.get(position);
             if (p != null ){
                 f.resetFragmentData(p);
             }
         }
 
         return f;
     }
 
     @Override
      public int getItemPosition(Object object) {
         return POSITION_NONE;
     }
 
     @Override
     public int getCount() {
         return mRecList == null ? 0 : mRecList.size();
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值