zoukankan      html  css  js  c++  java
  • 【转】实现ViewPager懒加载的三种方法

    方法一

    在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

  • 相关阅读:
    C#(99):Queue<T>队列与Stack<T>堆栈
    C#(99):字典Dictionary<Tkey.TValue>与SortedList
    C#(99):列表:List<T>与HashSet和只读集合
    C#(99):C#数组Array
    C#(99):枚举类型与位域枚举Enum
    C#(99):结构类型:Struct
    C#(99):定义类成员(属性、方法、索引、运算符、事件)、接口实现
    C#(99):定义类、System.Object对象、构造函数与析构函数、抽象类与静态类
    SuperSocket.ClientEngine介绍
    C#(99):五、并行编程
  • 原文地址:https://www.cnblogs.com/ryq2014/p/6198319.html
Copyright © 2011-2022 走看看