【转】实现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

时间: 2024-10-15 13:19:53

【转】实现ViewPager懒加载的三种方法的相关文章

vue+webpack实现懒加载的三种方式

实现方式: 1.webpack method require.ensure([''], callback, chunkName) ; 2.es6 motehod import() import().then() import(/* webpackChunkName: async-chunk-name */ /* webpackMode: lazy */ modulename) 需要安装bable插件 syntax-dynamic-import,因为import只能出现在页面顶部 具体实现: 第一

QML中文件的加载(三种方法)

在这里小小总结一下QML文件中如何加载QML文件与JavaScript文件. 1.QML文件中加载JavaScript文件 语法: import <ModuleIdentifier> <Version.Number> [as <Qualiflier>] ModuleIdentifier为URL: Version.Number为版本号: Qualifier为自定义命名: 示例代码如下: Qml文件: 图一 Js文件 图二 注:将js文件引入后可直接调用里面的函数,自定义命

ViewPager懒加载

一.运行效果图 打印Log图 二.工程结构 三.实现代码 1.创建Fragment需要继承的抽象类,即父类 package com.example.lazyloaddemoa.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.text.TextUtils; import andr

vue项目实现路由按需加载(路由懒加载)的3种方式

为什么需要懒加载? 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时 vue异步组件es提案的import()webpack的require,ensure()1 . vue异步组件技术 ==== 异步加载 vue-router配置路由 , 使用

Hibernate的懒加载session丢失解决方法

在web.xml加入spring提供的过滤器,延长session的生命周期 <!--Hibernate的懒加载session丢失解决方法 --> <filter> <filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class&

(Object-C)学习笔记 --OC的懒加载和单例方法

OC的懒加载 什么是懒加载: 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化. 懒加载的好处 (1)不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 (2)每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 懒加载的例子: #import "MusicTableViewController.h&quo

图片懒加载 lazyload.js使用方法

lazyload是一个用Javascript编写的jQuery插件,它可以延迟加载长页面中的图片,在浏览器可视区域外的图片将不会被载入,直到用户将它们滚动到它们所在的位置. 跟bootstrap一样,lazyload.js也是依赖于jQuery <script src="resources/js/jquery-1.8.3.min.js"></script> <script src="resources/js/jquery.lazyload.min

React 路由懒加载的几种实现方案

这篇文字简单的介绍了React在路由懒加载方面的几种实现方案. 传统的两种方式 import() 符合ECMAScript提议的import()语法,该提案与普通 import 语句或 require 函数的类似,但返回一个 Promise 对象.这意味着模块时异步加载的 webpack v2+ 使用 使用方式 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function component() {  return import( /* webpackChu

懒加载的3种实现方式

优势 性能收益:浏览器加载图片.decode.渲染都需要耗费资源,懒加载能节约性能消耗,缩短onload事件时间. 节约带宽:这个不需要解释. 通常,我们在html中展示图片,会有两种方式: img 标签 css background-image img的懒加载实现 img有两种方式实现懒加载: 事件监听(scroll.resize.orientationChange) <!DOCTYPE html> <html lang="en"> <head>