viewpager和fragment的懒加载。
以这个为例http://www.2cto.com/kf/201501/368954.html
①BaseFragment 中重写setUserVisibleHint()设置标记,在加载时判断。
//关闭预加载,默认一次只加载一个Fragment
②mViewPager.setOffscreenPageLimit(1);
但是,这个注释是不正确的。具体打log可以发现,加载0时会预加载1,加载2时会加载1和3.
我们看源码
1,首先是方法实现
/**
* Set the number of pages that should be retained to either side of the
* current page in the view hierarchy in an idle state. Pages beyond this
* limit will be recreated from the adapter when needed.
*
* <p>This is offered as an optimization. If you know in advance the number
* of pages you will need to support or have lazy-loading mechanisms in place
* on your pages, tweaking this setting can have benefits in perceived smoothness
* of paging animations and interaction. If you have a small number of pages (3-4)
* that you can keep active all at once, less time will be spent in layout for
* newly created view subtrees as the user pages back and forth.</p>
*
* <p>You should keep this limit low, especially if your pages have complex layouts.
* This setting defaults to 1.</p>
*
* @param limit How many pages will be kept offscreen in an idle state.
*/
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
2,这个mOffscreenPageLimit,在 void populate(int newCurrentItem)用到,用来计算start和end,然后根据start和end分别做了循环(具体参见源代码)
final int pageLimit = mOffscreenPageLimit;
final int startPos = Math.max(0, mCurItem - pageLimit);
final int N = mAdapter.getCount();
final int endPos = Math.min(N-1, mCurItem + pageLimit);
最后在循环中,如果为null的,执行
ii = addNewItem(pos, itemIndex + 1);
3,在
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;
}
4,在adapter中,FragmentPagerAdapter中
@Override
public Object instantiateItem(ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
final long itemId = getItemId(position);
// Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
return fragment;
}
5,所以我们看到 fragment = getItem(position);
整理一下,在getItem中加载的fragment,依次被FragmentPagerAdapter中的instantiateItem()方法,ViewPager中的addNewItem方法、populate()方法调用。
调用时根据mOffscreenPageLimit预加载,而这个最小是1,所以肯定会预加载。
在最上面的例子中,已经new了,只是没有初始化等。
所以如果我们要想设置为0。只能自定义一个,然后改为0就好了。
页:
[1]