方法一
在Fragment可见时请求数据。此方案仍预加载了前后的页面,但是没有请求数据,只有进入到当前Framgent时才请求数据。
优点:实现了数据的懒加载
缺点:一次仍是三个Framgment对象,不是完全意义的懒加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class FragmentSample extends Fragment{ ....... @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { requestData(); // 在此请求数据 } } ...... } |
方法二
直接修改ViewPager源码。通过查看ViewPager源码可知,控制其预加载的是一个常量 DEFAULT_OFFSCREEN_PAGES,其默认值为1,表示当前页面前后各预加载一个页面,在这里我们直接将其设置为0即可,即去掉预加载。但是,这样有一个问题,那就是在使用其他控件时需要传入ViewPager时,这个就不能用了。
优点:完全屏蔽掉了预加载
缺点:应用太受限制,比如使用ViewPagerIndicator时需要传入ViewPager对象,这时傻眼了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 注意,这是直接拷贝的ViewPager的源码,只修改了注释处的代码 public class LazyViewPager extends ViewGroup { private static final String TAG = "LazyViewPager"; private static final boolean DEBUG = false; private static final boolean USE_CACHE = false; // 默认为1,即前后各预加载一个页面,设置为0去掉预加载 private static final int DEFAULT_OFFSCREEN_PAGES = 0; private static final int MAX_SETTLE_DURATION = 600; // ms static class ItemInfo { Object object; int position; boolean scrolling; } private static final Comparator<ItemInfo> COMPARATOR = new Comparator<ItemInfo>() { @Override public int compare(ItemInfo lhs, ItemInfo rhs) { return lhs.position - rhs.position; } }; ............ } |
方法三
直接继承ViewPager,结合PagerAdapter实现懒加载。该方案是我用到的最完善的方法,完全的懒加载,每次只会建立一个Fragment对象。
优点:完全屏蔽预加载
缺点:稍微复杂,需要自定义,开源库地址
这个库就4个类,作者通过继承ViewPager(保证其普适性)、自定义ViewPagerAdapter和 LazyFragmentPagerAdapter以及设置懒加载的标记接口,很好的实现了懒加载。感谢作者。
在此贴出关键代码,有兴趣的同学可以学习下。
LazyViewPager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
public class LazyViewPager extends ViewPager { private static final float DEFAULT_OFFSET = 0.5f; private LazyPagerAdapter mLazyPagerAdapter; private float mInitLazyItemOffset = DEFAULT_OFFSET; public LazyViewPager(Context context) { super(context); } public LazyViewPager(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LazyViewPager); setInitLazyItemOffset(a.getFloat(R.styleable.LazyViewPager_init_lazy_item_offset, DEFAULT_OFFSET)); a.recycle(); } /** * change the initLazyItemOffset * @param initLazyItemOffset set mInitLazyItemOffset if {@code 0 < initLazyItemOffset <= 1} */ public void setInitLazyItemOffset(float initLazyItemOffset) { if (initLazyItemOffset > 0 && initLazyItemOffset <= 1) { mInitLazyItemOffset = initLazyItemOffset; } } @Override public void setAdapter(PagerAdapter adapter) { super.setAdapter(adapter); mLazyPagerAdapter = adapter != null && adapter instanceof LazyPagerAdapter ? (LazyPagerAdapter) adapter : null; } @Override protected void onPageScrolled(int position, float offset, int offsetPixels) { if (mLazyPagerAdapter != null) { if (getCurrentItem() == position) { int lazyPosition = position + 1; if (offset >= mInitLazyItemOffset && mLazyPagerAdapter.isLazyItem(lazyPosition)) { mLazyPagerAdapter.startUpdate(this); mLazyPagerAdapter.addLazyItem(this, lazyPosition); mLazyPagerAdapter.finishUpdate(this); } } else if (getCurrentItem() > position) { int lazyPosition = position; if (1 - offset >= mInitLazyItemOffset && mLazyPagerAdapter.isLazyItem(lazyPosition)) { mLazyPagerAdapter.startUpdate(this); mLazyPagerAdapter.addLazyItem(this, lazyPosition); mLazyPagerAdapter.finishUpdate(this); } } } super.onPageScrolled(position, offset, offsetPixels); } } public abstract class LazyFragmentPagerAdapter extends LazyPagerAdapter<Fragment> { private static final String TAG = "LazyFragmentPagerAdapter"; private static final boolean DEBUG = false; private final FragmentManager mFragmentManager; private FragmentTransaction mCurTransaction = null; public LazyFragmentPagerAdapter(FragmentManager fm) { mFragmentManager = fm; } @Override public void startUpdate(ViewGroup container) { } @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(container, position); if (fragment instanceof Laziable) { mLazyItems.put(position, fragment); } else { mCurTransaction.add(container.getId(), fragment, name); } } if (fragment != getCurrentItem()) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object + " v=" + ((Fragment) object).getView()); final long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId); if (mFragmentManager.findFragmentByTag(name) == null) { mCurTransaction.detach((Fragment) object); } else { mLazyItems.remove(position); } } @Override public Fragment addLazyItem(ViewGroup container, int position) { Fragment fragment = mLazyItems.get(position); if (fragment == null) return null; final long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId); if (mFragmentManager.findFragmentByTag(name) == null) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } mCurTransaction.add(container.getId(), fragment, name); mLazyItems.remove(position); } return fragment; } @Override public void finishUpdate(ViewGroup container) { if (mCurTransaction != null) { mCurTransaction.commitAllowingStateLoss(); mCurTransaction = null; mFragmentManager.executePendingTransactions(); } } @Override public boolean isViewFromObject(View view, Object object) { return ((Fragment) object).getView() == view; } public long getItemId(int position) { return position; } private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; } /** * mark the fragment can be added lazily */ public interface Laziable { } } |
友情提示:填充LazyViewPager的Fragment一定要实现接口LazyFragmentPagerAdapter.Laziable,其实就是一个标记。
原文链接:
http://answerzhao.github.io/2016/06/06/%E5%AE%9E%E7%8E%B0ViewPager%E6%87%92%E5%8A%A0%E8%BD%BD%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95/#
其他参考地址:
http://www.jianshu.com/p/104be7cd72b6
http://www.cnblogs.com/dasusu/p/5926731.html