详解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()方法视图未更新

学校在考完试后给我们加了一周的Android课,本来考完试很累了,还一天不让休息,天天起早去上课π__π。最后交课程设计, 模仿彩虹天气写一个天气应用,下面是我们组做的: 城市切换使用的Vi...
  • daditao
  • daditao
  • 2016年03月30日 22:17
  • 696

Fragment+ViewPager动态更新问题

ViewPager嵌套Fragment在应用中使用频繁,但会遇到很多问题。 这次要做的是,应用首页在未登录状态下只显示一个页面,当用户登陆后需要显示好几页,并实现轮播效果。 最开始在ViewPag...
  • beau_lei
  • beau_lei
  • 2017年03月27日 15:15
  • 684

关于调用 FragmentPagerAdapter.notifyDataSetChanged() 不能更新

public int getItemPosition(Object object) { return POSITION_NONE; } yuanhttp://blog.sina.com.cn...
  • iloveaman
  • iloveaman
  • 2014年07月30日 15:34
  • 393

Android ViewPager+Fragment数据传递和动态刷新成熟解决方案

Fragment的数据传递用起来很简单,但深究起来,其中的很多坑想必大家都已经历过。ViewPager的适配器如何动态的刷新数据也是个头疼的问题。把这俩货放在一起很常见,但却是坑中坑。 通过长时间的发...
  • u011192530
  • u011192530
  • 2016年11月19日 22:23
  • 8573

ViewPager嵌套Fragment实现item实时更新的两种方式

ViewPager嵌套Fragment实现item实时更新的两种方式引言 很多项目中需要viewpager嵌套多个fragment实现切换的这种大框架,但是效果实现简单,想要实现item里数据实时...
  • qwe490139301
  • qwe490139301
  • 2016年07月25日 10:52
  • 1637

使用getChildFragmentManager解决Fragment嵌套ViewPager出现空白

我们先看一下这种情况是什么样的: 我们可以看到第二个Fragment里面的ViewPager显示的内容为空白,为什么呢?关键代码在这里:viewPager.setAdapter(new OtherF...
  • Small_Lee
  • Small_Lee
  • 2016年02月29日 17:07
  • 2686

动态更新ViewPager中的Fragment

http://stackoverflow.com/questions/7263291/viewpager-pageradapter-not-updating-the-view/8024557#8024...
  • zhuhai__yizhi
  • zhuhai__yizhi
  • 2016年07月22日 15:32
  • 333

Android-ViewPager+Fragment数据更新问题

因为FragmentPagerAdapter内部存在缓存,因此调用notifyDataSetChanged()并不能够去更新Fragment的内容。 参考:http://www.devba.com/i...
  • goldenfish1919
  • goldenfish1919
  • 2015年08月14日 14:58
  • 6719

Activity+fragment+ViewPager方法调用

说明:        MainActivity中有四个Fragment,其中第三个fragment中用的是fragment+viewPager 1、开启应用: 2、跳转到fragment3 ...
  • eagle1054
  • eagle1054
  • 2016年05月04日 21:53
  • 395

【安卓笔记】ViewPager+Fragment布局中的Fragment数据更新

------------------------------------------------------------------------------------- 请尊重作者劳动成果,转...
  • RowandJJ
  • RowandJJ
  • 2014年03月24日 23:38
  • 8966
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:详解ViewPager调用FragmentPagerAdapter.notifyDataSetChanged()不能更新Fragment
举报原因:
原因补充:

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