ViewPager在日常开发中经常使用. 在一个Pager页面比较复杂时候回使用Fragment来替代View作为ViewPager的页面显示. FragmentPagerAdapter来替代PagerAdapter作为适配器.
参考文档:
但是ViewPager默认是加载三个页面, 当前页面以及左右页面. 如果一个页面的数据量非常大, 会造成流量的浪费和卡顿. 很可能预加载的页面用户根本不会去查看, 这就是无意义的加载.
所以需要禁止ViewPager的预加载<也称为懒加载>, 在处于用户可见时进行数据的加载.
这里我将介绍两种懒加载的方法
Fragment懒加载
关键方法
关键方法是Fragment中setUserVisibleHint()
方法 该方法有一个布尔类型参数isVisibleToUser
, 可以通过参数判断当前Fragment是否处于用户可见状态. 在Fragment可见时该参数为true, 不可见时为false.
1
2
3
4
|
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
}
|
回调时机
该方法总共执行三次. 依照以下顺序:
- 创建Fragment. 参数为false. 比onCreate先执行.
- 显示当前界面. 且参数为true. 比onCreate先执行.
- 离开当前界面. 参数为false
注意
用以上的方法实现懒加载需要注意三点:
- 因为关键方法会在onCreate之前执行, 所以需要判断是否初始化控件
- FragmentPagerAdapter并不会销毁实例所以需要手动更改成员变量
- 如果想不每次切换页面都重新加载数据可以进行缓存和判断是否加载过数据
示例
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
|
public
class CustomFragmentB extends Fragment {
@BindView(R.id.btn)
Button mBtn;
Unbinder unbinder;
public String mText;
private
boolean mIsVisibleToUser;
private
boolean mIsInitView;
private
boolean mIsLoadData;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_custom,
null);
unbinder = ButterKnife.bind(
this, view);
if (
null != mText) {
mBtn.setText(mText);
}
mIsInitView =
true;
loadData();
return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
mIsVisibleToUser = isVisibleToUser;
loadData();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
mIsInitView =
false;
}
@OnClick(R.id.btn)
public void onClick() {
mText =
"吴彦祖";
mBtn.setText(mText);
}
public void loadData() {
if (mIsInitView && mIsVisibleToUser && !mIsLoadData) {
mBtn.setText(
"吴彦祖");
mIsLoadData =
true;
}
}
}
|
※ 上面的方法有两个地方调用了数据加载的方法. 因为第一次进入ViewPager或者跨页面进行跳转的这两种情况下都是没有进行预加载页面的. 就会导致setUserVisibleHint
方法比onCreateView
方法先执行. 所以这种情况数据的加载必须在最后面的方法内调用
setUserVisibleHint 和 onCreateView 两个方法必须同时执行后才能进入数据加载.