`

【转】详解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();
    }
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics