一。属性
1.setPageMargin2.setOffscreenPageLimit二。
1.什么时候调用PagerAdapter.instantiateItem//在populate中,遍历mCurItem之前的, addNewItem满足这个条件的pos == ii.position && !ii.scrolling
遍历mCurItem之后的, addNewItem满足这个条件的pos == ii.position && !ii.scrolling
ItemInfo addNewItem(int position, int index) { ItemInfo ii = new ItemInfo(); ii.position = position; ii.object = mAdapter.instantiateItem(this, position); ii.widthFactor = mAdapter.getPageWidth(position); if (index < 0 || index >= mItems.size()) { mItems.add(ii); } else { mItems.add(index, ii); } return ii; }
void populate(int newCurrentItem) { ... ... // Locate the currently focused item or add it if needed. ItemInfo curItem = null; for (curIndex = 0; curIndex < mItems.size(); curIndex++) { final ItemInfo ii = mItems.get(curIndex); if (ii.position >= mCurItem) { if (ii.position == mCurItem) curItem = ii; break; } } if (curItem == null && N > 0) { curItem = addNewItem(mCurItem, curIndex); } ... ... // Fill 3x the available width or up to the number of offscreen // pages requested to either side, whichever is larger. // If we have no current item we have no work to do. 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; } } ... ... 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; } } } }
2.什么时候调用PagerAdapter.destroyItem
//在dataSetChanged中遍历mItems,利用PagerAdapter.getItemPosition() destroyItem pos//在populate中,遍历mCurItem之前的, destroyItem满足这个条件的pos == ii.position && !ii.scrolling遍历mCurItem之后的, destroyItem满足这个条件的pos == ii.position && !ii.scrolling
void 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; } ... ... }
原理:
3.什么时候调用populate(item)
item是curItemvoid setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { ... ... if (mFirstLayout) { // We don't have any idea how big we are yet and shouldn't have any pages either. // Just set things up and let the pending layout handle things. mCurItem = item; if (dispatchSelected) { dispatchOnPageSelected(item); } requestLayout(); } else { populate(item); scrollToItem(item, smoothScroll, velocity, dispatchSelected); } }
在onRestoreInstanceState,
onTouchEvent(MotionEvent ev) MotionEvent.ACTION_UP mIsBeingDragged==true时,程序员调用setCurrentItem,setAdapter, endFakeDrag时dataSetChanged,private class PagerObserver extends DataSetObserver { PagerObserver() { } @Override public void onChanged() { dataSetChanged(); } @Override public void onInvalidated() { dataSetChanged(); } }
PagerAdapter.java:
public void notifyDataSetChanged() { synchronized (this) { if (mViewPagerObserver != null) { mViewPagerObserver.onChanged(); } } mObservable.notifyChanged(); }
也就说除非用户自己调用setCurrentItem,setAdapter, endFakeDrag,PagerAdapter.notifyDataSetChanged ,只有在ACTION_UP时,才会调用populate(item)