前一篇文章我们介绍了viewpager的预加载特性(这里作者强烈建议读下:)
这篇文章我们主要介绍 viewpager懒加载实现
ViewPager+Fragment的搭配在日常开发中也比较常见,下图为今日头条app的截图
ViewPager控件有个特有的预加载机制,即默认情况下当前页面左右两侧的1个页面会被加载,以方便用户滑动切换到相邻的界面时,可以更加顺畅的显示出来,但也会带来一个问题,耗费用户多余的流量,那么如何避免,那就需要我们实现懒加载。
懒加载
所谓的懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据.这样可以提高所属Activity的初始化速度,也可以为用户节省流量.而这种懒加载的方式也已经/正在被诸多APP所采用.
如何实现
首先Fragment为我们提供了一个方法setUserVisibleHint(boolean isVisibleToUser)
,其中的参数isVisibleToUser
就是表示该Fragment的UI对于用户是否可见。
public void setUserVisibleHint(boolean isVisibleToUser) {
if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
&& mFragmentManager != null && isAdded()) {
mFragmentManager.performPendingDeferredStart(this);
}
mUserVisibleHint = isVisibleToUser;
mDeferStart = mState < STARTED && !isVisibleToUser;
if (mSavedFragmentState != null) {
// Ensure that if the user visible hint is set before the Fragment has
// restored its state that we don't lose the new value
mSavedUserVisibleHint = mUserVisibleHint;
}
}
此方法来设置Fragment的UI对用户是否可见,当该页面对用户可见/不可见时,系统都会回调此方法。
我们可以重写此方法,然后根据回调的isVisibleToUser
参数来进行相关的逻辑判断,以达到懒加载的效果,比如如果isVisibleToUser==true
的话表示当前Fragment对用户可见,此时再去加载页面数据。
由于ViewPager内会装载多个Fragment,而这种懒加载机制对于各个Fragment属于共同操作,因此适合将其抽取到BaseFragment中。
需要注意一下: setUserVisibleHint(boolean isVisibleToUser)
方法会多次回调,而且可能会在onCreateView()
方法执行完毕之前回调.如果isVisibleToUser==true,然后进行数据加载和控件数据填充,但是onCreateView()
方法并未执行完毕,此时就会出现NullPointerException空指针异常。
所以懒加载需满足两个条件
-
onCreateView()
方法执行完毕 -
setUserVisibleHint(boolean isVisibleToUser)
方法返回true
下面给出basefragment的代码:
public abstract class BaseFragment extends Fragment {
//Fragment的View加载完毕的标记
private boolean isViewCreated;
//Fragment对用户可见的标记
private boolean isUIVisible;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//fragment的View加载完毕
isViewCreated = true;
lazyLoad();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isUIVisible = true;
lazyLoad();
} else {
isUIVisible = false;
}
}
//定义抽象方法loadData(),具体加载数据的工作,交给子类去完成
protected abstract void loadData();
private void lazyLoad() {
/**
*这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,
必须确保onCreateView加载完毕且页面可见,才加载数据
*/
if (isViewCreated && isUIVisible) {
loadData();
//数据加载完毕,恢复标记,防止重复加载
isViewCreated = false;
isUIVisible = false;
}
}
}
注意:数据加载完毕要恢复标记,防止数据重复加载
总结:
讲到这里,相信大家对懒加载已经有了一定的了解,接下来就运用到我们的项目里吧!!!
.