进入viewpager,我们终于找到了viewpager中控制数据变更的重点方法dataSetChanged ,这个方法如下:
void
dataSetChanged () {
boolean
needPopulate = mItems .size() < mOffscreenPageLimit *
2
+
1
&&
mItems.size() < mAdapter.getCount();
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 ) {
newCurrItem = Math. max(
0
, Math.min(mCurItem, mAdapter.getCount() -
1
));
needPopulate =
true
;
}
continue
;
}
if
(ii.position != newPos) {
if
(ii.position == mCurItem ) {
newCurrItem = newPos;
}
ii. position = newPos;
needPopulate =
true
;
}
}
if
(isUpdating) {
mAdapter.finishUpdate(
this
);
}
Collections. sort(mItems, COMPARATOR);
if
(needPopulate) {
final
int
childCount = getChildCount();
for
(
int
i =
0
; i < childCount; i++) {
final
View child = getChildAt(i);
final
LayoutParams lp = (LayoutParams) child.getLayoutParams();
if
(!lp.isDecor ) {
lp. widthFactor =
0
.f;
}
}
setCurrentItemInternal(newCurrItem,
false
,
true
);
requestLayout();
}
}
重点看这样一行代码:
final
int
newPos = mAdapter.getItemPosition(ii.object );
if
(newPos == PagerAdapter.POSITION_UNCHANGED ) {
continue
;
}
官方对getItemPosition()的解释是:
Called when the host view is attempting to determine
if
an item’s position has changed. Returns POSITION_UNCHANGED
if
the position of the given item has not changed orPOSITION_NONE
if
the item is no longer present in the adapter.
The
default
implementation assumes that items will never change position and always returns POSITION_UNCHANGED.
意思是如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,而返回POSITION_UNCHANGED
解决方案:
所以我们可以尝试着修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。