問題描述:
在使用ViewPager的適配器刪除適配器里一個Item后依然會,而刪除的這個item依然會保留緩存,適配器不會重新加載更新數據.如下代碼:
public class TReleaseCircleZoomablePagerAdapter extends PagerAdapter { private List<TReleaseCircleBase.Pic> mImageUrlList = new ArrayList<>(); public void removeItem(int position){ mImageUrlList.remove(position); notifyDataSetChanged(); } //....略
在這個代碼里removeItem(int position)是希望清理適配器List里的一項item,並且重新刷新.但是其實真實情況是並不會重新刷新...... 在滑動超過3個頁面后才會讓你那個刪除item消失.
解決辦法:
依然在這個適配器里重寫public int getItemPosition(@NonNull Object object)方法
public class TReleaseCircleZoomablePagerAdapter extends PagerAdapter { private List<TReleaseCircleBase.Pic> mImageUrlList = new ArrayList<>(); public void removeItem(int position){ mImageUrlList.remove(position); notifyDataSetChanged(); } @Override public int getItemPosition(@NonNull Object object) { // return super.getItemPosition(object); return POSITION_NONE; } //略......
注意關鍵點是返回 POSITION_NONE
為什么呢?
為什么我改了這個之后就可以在刪除item后更新view了呢?好奇心害死貓,我們進一步探究一下.
首先我們看看 return super.getItemPosition(object); 父類里寫的返回值到底里面有啥
/** * 在主視圖嘗試確定項目的位置時調用 * 已經改變。 如果給定的位置,則返回{@link #POSITION_UNCHANGED} * 如果適配器中不再存在該項,則item未更改或{@link #POSITION_NONE}。 * * <p>The default implementation assumes that items will never * change position and always returns {@link #POSITION_UNCHANGED}. * * @param object Object representing an item, previously returned by a call to * {@link #instantiateItem(View, int)}. * @return object's new position index from [0, {@link #getCount()}), * {@link #POSITION_UNCHANGED} if the object's position has not changed, * or {@link #POSITION_NONE} if the item is no longer present. */ public int getItemPosition(@NonNull Object object) { return POSITION_UNCHANGED; }
很好上面的意思是
如果視圖item已經是加載過的,就使用 POSITION_UNCHANGED 來標識,表示這個item不需要重復更新
如果item在適配器里不存在,就說item未加載過,就使用 POSITION_NONE 來標識,標識這個item需要更新一次
接着繼續探究下ViewPager是怎么調用getItemPosition()的
void dataSetChanged() { // This method only gets called if our observer is attached, so mAdapter is non-null. final int adapterCount = mAdapter.getCount(); mExpectedAdapterCount = adapterCount; boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 && mItems.size() < adapterCount; int newCurrItem = mCurItem; boolean isUpdating = false; 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 (newPos == PagerAdapter.POSITION_UNCHANGED) 和 if (newPos == PagerAdapter.POSITION_NONE) 就已經破案了...,只能說google真會寫方法名稱...