实现viewpager懒加载的三种方法

LittleEyes LittleEyes     2022-08-18     513

关键词:

方法一

在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

androidfragment+viewpager的懒加载实现(代码片段)

...、页面刷新和资源释放等逻辑操作。但是当Fragment遇上了ViewPager,事情就变得有点不一样了。Fragment的生命周期变得不再那么可控,当显示FragmentA时,相邻 查看详情

androidfragment+viewpager的懒加载实现(代码片段)

...、页面刷新和资源释放等逻辑操作。但是当Fragment遇上了ViewPager,事情就变得有点不一样了。Fragment的生命周期变得不再那么可控,当显示FragmentA时,相邻的FragmentB的一些生命周期方法也会触发。这是因为ViewPager为了... 查看详情

viewpager懒加载

一、运行效果图  打印Log图  二、工程结构 三、实现代码1、创建Fragment需要继承的抽象类,即父类packagecom.example.lazyloaddemoa.fragment;importandroid.os.Bundle;importandroid.support.annotation.Nullable;importandroid 查看详情

viewpager+fragment懒加载

...尹star链接:http://www.jianshu.com/p/c5d29a0c3f4c來源:简书 ViewPager+Fragment的模式再常见不过了,以国民应用微信为例,假设微信也是ViewPager+Fragment的实现方式,那表现形式上就是一个ViewPager管理了四个Fragment,左右滑动来回切换。... 查看详情

viewpager详解填充fragment和懒加载(代码片段)

ViewPager详解(三)Fragment的填充和懒加载实现个人主页Demo下载地址效果图一、ViewPager基础学习请上传送门ViewPager详解(一)简单介绍和使用ViewPager详解(二)广告轮播图ViewPager详解(三)引导页二... 查看详情

安卓中实现界面数据懒加载

...这个实现起来其实很简单,就是在一个Fragment中实现多个ViewPage的切换,再在ViewPage的上面放一个TabLayout,关联起来就可以实现联动效果。如果大家感觉不太明了的话,以后我可以专门写一篇关于Fragment中放入多个ViewPage的博客 查看详情

安卓中viewpager+tablayout+fragment懒加载怎么做

viewpager的预加载是无法取消的。但我们可以换一种思路来实现。取消预加载无非就是你的页面没有准备齐全,数据上或其它的还不足以加载一个正确的视图。你可以对这样的页面只写一个空视图,viewpager需要的List你可以组装好... 查看详情

java的viewpage+片段懒加载(代码片段)

查看详情

fragment数据懒加载及原理

...求。于是马上联想到可能是因为首页改版之后嵌套使用了ViewPager,业务未完全开放的那个fragment里嵌套了一个ViewPager,里面有多个fragment,这样每次打开首页都会去加载该page,然后是一连串的fragment初始化以及网络请求,所以为... 查看详情

java实现监听文件变化的三种方法,推荐第三种(代码片段)

...而进行加载。当然,在其他业务场景下,比如想实现配置文件的动态加载、日志文件的监听、FTP文件变动监听等都会遇到类似的场景。本文给大家提供三种解决方案,并分析其中的利弊,建议收藏,以备不时... 查看详情

androidviewpager+fragment懒加载数据可操作控件版

参考此博客【Android】Fragment懒加载和ViewPager的坑在使用ViewPager和Fragment的时候ViewPager会一次加载3个Fragment调用其生命周期函数有时候只需要加载一个这时候可以使用setUserVisibleHint函数在其中getUserVisibleHint()即可判断是否是正在使... 查看详情

线程的三种实现方法(代码片段)

线程的三种实现方法:(1)继承Thread类,重写run()方法;(2)实现Runnable接口,重写run()方法;(3)实现Callable接口,重写call()方法;方式一: 继承Thread类publicclassMyThreadDemopublicstaticvoidmain(String[]args)Threadthread=newMyThread();thread.... 查看详情

java实现定时任务的三种方法

java实现定时任务的三种方法详解java定时任务定时器的实现、java定时器介绍与Spring中定时器的配置java定时器简单了解 ------------------ java定时器执行多个方法 查看详情

servlet实现的三种方式

实现Servlet的三种方式:一个实现,两个继承/*==========================================*servlet的执行过程:*1.创建servlet对象(Tomcat执行)*2.第一次访问servlet时执行*init()方法该方法只执行一次*service()方法*3.之后每访问一次就执行一次servic... 查看详情

fragment懒加载预加载

 1.预加载viewpager.setOffscreenPageLimit(2);,默认是预加载1,可以结合懒加载使用。   如果希望进入viewpager,Fragment只加载一次,再次滑动不需加载(只有退出Activity), 可以重写viewpageradapter的getItem,去掉super  2.... 查看详情

js异步加载的三种方式

  js加载的缺点:加载工具方法没必要阻塞文档,过得js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。有些工具方法需要按需加载,用到再加载,不用不加载,。  默认正常模式... 查看详情

使用javascript判断图片是否加载完成的三种实现方式

有时需要获取图片的尺寸,这需要在图片加载完成以后才可以。有三种方式实现,下面一一介绍。一、load事件 <!DOCTYPEHTML><html><head><metacharset="utf-8"><title>img-loadevent</title></head><body><img 查看详情

react控制元素显示隐藏的三种方法

...display属性来控制元素显示和隐藏。通过className切换hide来实现元素的显示和隐藏。要注意的是,这几种方法也有使用的区别: 查看详情