关闭

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

标签: FragmentPagerAdapter
132人阅读 评论(0) 收藏 举报
分类:

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

代码默认实现如此。
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(inti = 0; i < mItems.size(); i++) {
            finalItemInfo ii = mItems.get(i);
            finalint 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
    publicint getItemPosition(Object object) {
        returnPOSITION_NONE;
    }

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

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

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

1
2
3
privatestatic String makeFragmentName(intviewId, longid) {
        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
publicclass CarTypeListAdapter extendsFragmentPagerAdapter {
 
    privatefinal ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> mRecList;
    protectedImageWorker mImageFetcher;
 
    publicCarTypeListAdapter(FragmentManager fm, ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> recList, ImageWorker worker) {
        super(fm);
        this.mRecList = recList;
        this.mImageFetcher = worker;
    }
 
    @Override
    publicFragment getItem(intposition) {
        CarTypeInfoFragment imageFragment = CarTypeInfoFragment.newInstance(mRecList.get(position), mImageFetcher);
        returnimageFragment;
    }
 
    publicObject instantiateItem(ViewGroup container, intposition) {
        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);
            }
        }
 
        returnf;
    }
 
    @Override
     publicint getItemPosition(Object object) {
        returnPOSITION_NONE;
    }
 
    @Override
    publicint getCount() {
        returnmRecList == null? 0: mRecList.size();
    }
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:22568次
    • 积分:538
    • 等级:
    • 排名:千里之外
    • 原创:34篇
    • 转载:7篇
    • 译文:0篇
    • 评论:4条