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

转载 2016年08月30日 12:08:03

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

代码默认实现如此。
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();
    }
}

为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?

在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,...

为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?

在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,...

为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment? 【转载】

在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,...

为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment

转自http://www.apkbus.com/android-90417-1-1.html 在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fra...

[Android] 为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?

原帖地址:http://www.apkbus.com/android-90417-1-1.html 原帖作者:aitian 在寻找getItem()的用途的时候找到了这篇文章,感觉作者理得很清晰。 ...

ViewPager中使用FragmentPagerAdapter.notifyDataSetChanged无法更新当前Fragment解决方案

最近,在使用ViewPager和FragmentPagerAdapter时遇到如下问题(为了说明问题先上图): 图一 图二 功能描述:该页面为ViewPager的实现,且一共有两个Fragment...

关于FragmentPagerAdapter.notifyDataSetChanged() 并不能更新

在一个 Android 应用中,我使用  FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时...

如何让FragmentPagerAdapter.notifyDataSetChanged()能够更新Fragment

转自: 在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment...

【Android】从源码分析PagerAdapter/FragmentPagerAdapter调用notifydataSetChanged()刷新的原理

相信用过viewpager的同学都会遇到调用notifydataSetChanged()后不刷新或者不符合预期的问题,今天就来分析分析这里的来龙去脉。这一切还得从viewpager的setAdapte...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:详解ViewPager调用FragmentPagerAdapter.notifyDataSetChanged()不能更新Fragment
举报原因:
原因补充:

(最多只允许输入30个字)