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(); } }