ViewPager部分源码分析一:加载数据

onMeasure()调用populate(),完成首次数据初始化。

populate()维护ViewPager的page,包括mItems和mAdapter。

populate():

if (curItem == null && N > 0) {
curItem = addNewItem(mCurItem, curIndex);
}

似乎在首次数据初始化时会用到。

if (curItem != null) {
float extraWidthLeft = 0.f;
int itemIndex = curIndex - 1;
ItemInfo ii = itemIndex >= 0 ? mItems.get(itemIndex) : null;
final int clientWidth = getClientWidth();
final float leftWidthNeeded = clientWidth <= 0 ? 0 :
2.f - curItem.widthFactor + (float) getPaddingLeft() / (float) clientWidth;
for (int pos = mCurItem - 1; pos >= 0; pos--) {
if (extraWidthLeft >= leftWidthNeeded && pos < startPos) {
if (ii == null) {
break;
}
if (pos == ii.position && !ii.scrolling) {
mItems.remove(itemIndex);
mAdapter.destroyItem(this, pos, ii.object);
if (DEBUG) {
Log.i(TAG, "populate() - destroyItem() with pos: " + pos +
" view: " + ((View) ii.object));
}
itemIndex--;
curIndex--;
ii = itemIndex >= 0 ? mItems.get(itemIndex) : null;
}
} else if (ii != null && pos == ii.position) {
extraWidthLeft += ii.widthFactor;
itemIndex--;
ii = itemIndex >= 0 ? mItems.get(itemIndex) : null;
} else {
ii = addNewItem(pos, itemIndex + 1);
extraWidthLeft += ii.widthFactor;
curIndex++;
ii = itemIndex >= 0 ? mItems.get(itemIndex) : null;
}
} float extraWidthRight = curItem.widthFactor;
itemIndex = curIndex + 1;
if (extraWidthRight < 2.f) {
ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null;
final float rightWidthNeeded = clientWidth <= 0 ? 0 :
(float) getPaddingRight() / (float) clientWidth + 2.f;
for (int pos = mCurItem + 1; pos < N; pos++) {
if (extraWidthRight >= rightWidthNeeded && pos > endPos) {
if (ii == null) {
break;
}
if (pos == ii.position && !ii.scrolling) {
mItems.remove(itemIndex);
mAdapter.destroyItem(this, pos, ii.object);
if (DEBUG) {
Log.i(TAG, "populate() - destroyItem() with pos: " + pos +
" view: " + ((View) ii.object));
}
ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null;
}
} else if (ii != null && pos == ii.position) {
extraWidthRight += ii.widthFactor;
itemIndex++;
ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null;
} else {
ii = addNewItem(pos, itemIndex);
itemIndex++;
extraWidthRight += ii.widthFactor;
ii = itemIndex < mItems.size() ? mItems.get(itemIndex) : null;
}
}
} calculatePageOffsets(curItem, curIndex, oldCurInfo);
}

第一个for循环实现当前page左边的page处理;当向左滑时,销毁左边的page;当向右滑时,增加左边的page。

第二个for循环实现当前page右边的page处理;当向左滑时,增加右边的page;当向右滑时,销毁右边的page。

即在ViewPager中始终保留的是3个page:左边,当前,右边。(没有override PagerAdapter.getPageWidth()方法的情形下!跟ViewPager的padding也有关系)

其中的两次增加page的情况:

onTouchEvent() --> ViewCompat.postInvalidateOnAnimation() --> BaseViewCompatImpl.postInvalidateOnAnimation() --> View.invalidate()

--> ..这一步也不知道是什么.. --> View.updateDisplayListIfDirty --> View.computeScroll() --> ViewPager.completeScroll() --> ViewCompat.postOnAnimation()

--> BaseViewCompatImpl.postOnAnimation() --> View.postDelayed() --> Handler.getPostMessage() --> 后面就是Handler对消息的处理了。

private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}

原来Messge里有一个callback,是Runnable类型的,Handler.handleCallback()在处理消息时就是:

private static void handleCallback(Message message) {
message.callback.run();
}

直接调用callback的run()方法。

这么一大串的事情,其实两次增加page的情况就是:ViewPager的mEndScrollRunnable最终在Handler.handleCallback()完成的。

private final Runnable mEndScrollRunnable = new Runnable() {
public void run() {
setScrollState(SCROLL_STATE_IDLE);
populate();
}
};

看到run()方法中的populate()方法了么!!

上一篇:javaweb之Filter详解


下一篇:JAVA通过XPath解析XML性能比较