在项目中经常会使用到 ViewPager + Fragment 结构,但是 ViewPager 默认会预加载当前 Fragment 左右各一个 Fragment,这样就做了一些多余操作,如请求了第二个页面的数据。我们这里并不想提前执行这些操作,希望等用户切换到某个 Fragment 才进行加载,所以需要取消预加载。在 ViewPager 中有个 void setOffscreenPageLimit(int limit)
方法可以设置预加载 Fragment 的数量,那么我们可不可以直接设为 0 来取消预加载呢,先来看一下源码:
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES;
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
+ DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
通过源码可以看出 ViewPager 默认预加载数为 1,并且最小预加载数也仅能为 1,所以该方法不能取消预加载。
Fragment 中有两个方法 void setUserVisibleHint(boolean isVisibleToUser)
和 boolean getUserVisibleHint()
,它们分别用作设置和获取 Fragment 的可见状态,可以运用这两个方法实现 Fragment 的懒加载:
public abstract class BaseFragment extends Fragment {
// Fragment 当前状态是否可见
protected boolean mVisible;
// 标志是否已被加载过,第二次就不再请求数据
private boolean mHasLoadedOnce;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflateView(inflater, container, savedInstanceState);
lazyLoad();
return view;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
mVisible = true;
onVisible();
} else {
mVisible = false;
onInvisible();
}
}
/**
* 说明:加载 View 视图
*/
protected abstract View inflateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
/**
* 说明:懒加载
*/
private void lazyLoad() {
if (!mVisible || mHasLoadedOnce) return;
lazyLoadData();
mHasLoadedOnce = true;
}
/**
* 说明:懒加载数据
*/
protected void lazyLoadData() {
}
/**
* 说明:Fragment 当前状态可见
*/
protected void onVisible() {
}
/**
* 说明:Fragment 当前状态不可见
*/
protected void onInvisible() {
}
}
继承 BaseFragment 重写 inflateView
和 lazyLoadData
方法即可实现 Fragment 的懒加载。