ViewPager的懒加载

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);
}

回调时机

该方法总共执行三次. 依照以下顺序:

  1. 创建Fragment. 参数为false. 比onCreate先执行.
  2. 显示当前界面. 且参数为true. 比onCreate先执行.
  3. 离开当前界面. 参数为false

注意

用以上的方法实现懒加载需要注意三点:

  1. 因为关键方法会在onCreate之前执行, 所以需要判断是否初始化控件
  2. FragmentPagerAdapter并不会销毁实例所以需要手动更改成员变量
  3. 如果想不每次切换页面都重新加载数据可以进行缓存和判断是否加载过数据

示例

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 两个方法必须同时执行后才能进入数据加载.