`

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

 
阅读更多
转载自
http://www.blog4app.com/?p=62

我的问题:fragment展示网络down下来的图品,列表由一张图到多张的时候使用


@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

能解决问题




但是列表图片只有一张,需要更新为另外一张的时候,不行
,则需要重载
public Object instantiateItem(ViewGroup container, int position) 
更新fragment中的数据来实现了
感谢原博客博主不吝分享




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

代码默认实现如此。
FragmentPagerAdapter调用notifyDataSetChanged后,执行mObservable.notifyChanged()。mObservable对象的初始化,是在ViewPager调用setAdapter时被赋值的,对应的类叫PagerObserver。PagerObserver的dataSetChanged方法如下:
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掉。
@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }


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

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

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

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();
    }
}
分享到:
评论

相关推荐

    ViewPager底部条跟随viewpager动.rar

    10. **适配器的notifyDataSetChanged()**:当数据源发生变化时,需要调用PagerAdapter的`notifyDataSetChanged()`方法,使ViewPager重新加载数据。 总结来说,这个压缩包中的代码和资源文件应该能帮助开发者理解并...

    viewPager演示

    通常,你需要通过更新PagerAdapter的数据源并调用`notifyDataSetChanged()`来实现页面的动态增删。 7. **自定义滑动动画** - 可以通过继承`ViewPager.PageTransformer`并实现`transformPage()`方法来自定义页面...

    ViewPager.rar

    当某个页面内容发生变化时,可以调用`notifyDataSetChanged()`通知ViewPager数据已更新,ViewPager会重新加载相应页面。 **9. 限制滑动范围** 通过`setOffscreenPageLimit(int limit)`方法可以设置预加载的页面...

    ViewPagerDemo

    - 注意适配器的`notifyDataSetChanged()`方法的调用,以确保数据更新时页面正确显示。 总结,ViewPager是Android开发中实现多页面滑动的重要组件,结合页面适配器、指示器和自定义监听,可以创建出丰富的用户界面。...

    安卓viewpage框架

    4. 动态添加/删除页面:通过调用`PagerAdapter.notifyDataSetChanged()`方法,可以在运行时动态修改页面集合,实现动态加载和删除页面。 四、底部导航菜单结合ViewPage 1. 结合`BottomNavigationView`:`Bottom...

    ViewPager用法

    常用的实现类有`FragmentPagerAdapter`和`FragmentStatePagerAdapter`,它们分别用于管理`Fragment`对象,其中`FragmentStatePagerAdapter`更适用于需要节省内存的情况,因为它会在不显示的Fragment上执行销毁操作。...

    使用ViewPager实现高仿launcher拖动效果.rar

    6. **添加和移除页面**:在运行时动态添加或移除页面是可能的,只需要更新PagerAdapter的数据集并调用其`notifyDataSetChanged()`方法。 7. **Transformer动画**:通过设置PageTransformer,我们可以自定义页面切换...

    初始集成的viewpage

    - 保持`PagerAdapter`的更新机制正确,当数据改变时,调用`notifyDataSetChanged()`通知`ViewPager`更新。 以上就是关于“初始集成的viewpage”的主要知识点,通过理解和掌握这些内容,开发者可以顺利地在项目中...

    Android ViewPager使用不错的代码-IT计算机-毕业设计.zip

    - **设置适配器**:在Activity或Fragment中初始化ViewPager,并调用setAdapter方法传入适配器实例。 - **关联Indicator(可选)**:为了视觉上更好地指示当前页,可以添加TabLayout或其他指示器与ViewPager联动。 ...

    Viewpager滑屏经典例子

    3. **添加和移除页面**:如果你的应用需要动态添加或移除页面,可以通过调用`notifyDataSetChanged()`通知ViewPager数据已更新。 **二、ViewPagerIndicator介绍** 1. **Indicator作用**:ViewPagerIndicator是页面...

    Android 中ViewPager重排序与更新实例详解

    总之,要实现在Android中ViewPager的重排序和更新,关键在于适当地覆写`PagerAdapter`的`getItemPosition()`方法,正确地处理数据源的变更,并在数据源更改后调用`notifyDataSetChanged()`。通过理解并运用这些知识...

    Android ViewPager 的使用总结

    - 如果需要在运行时动态增加或减少页面,可以通过Adapter的方法实现,例如`addView()`、`removeView()`,然后调用`notifyDataSetChanged()`通知ViewPager数据集已更改。 9. **监听页面切换**: - 可以通过实现`...

    AndroidViewPage示例-ViewPagerIndicator

    - 如果`ViewPager`的数据源是动态加载的,记得在数据加载完成后调用`notifyDataSetChanged()`。 - 避免在主线程中进行耗时操作,确保流畅的用户体验。 通过以上步骤,你就可以在你的Android应用中实现一个功能...

Global site tag (gtag.js) - Google Analytics