背景
-
项目中不可避免会用到,这里记录一下,方便自己和同学们,好记性不如烂笔头。
-
理解后就不用专门记了,因为也确实没有太多复杂的东西。
-
因为 viewPager 的预加载机制,所以我们为了让 fragment 使用起来更加流畅,提升性能,所以需要对 fragment 做一个懒加载的操作,当 fragment 对用户不可见时不加载数据。
分析实现
- 最开始的 fragment 代码如下:
package com.example.myapplication.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.myapplication.R;
/**
* 懒加载写法
*/
public class MyFragment extends Fragment {
public MyFragment() {
// Required empty public constructor
}
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if (view == null && savedInstanceState == null){
view = inflater.inflate(R.layout.fragment_my, container, false);
}
return view;
}
}
这个没有疑问。
- 只有当 fragment 对用户可见且 fragment 的视图已经加载完成以后,我们才可以做对应的数据加载操作,所以这里引入两个布尔变量分别标识,如下图示:
初始化均赋值为 false。
- 因为是跟 viewPager 相结合,所以在 fragment 中判断对用户是否可见我们重写
setUserVisibleHint
生命周期方法进行判断,如下图示:
- 在 onCreateView 方法中对view已经加载完成标识置为 true,如下图示:
- 所以此时当对用户可见且 view 已经加载完成后,我们在 onResume 方法中做懒加载操作,如下图示:
- 此时做完懒加载操作后,记得恢复先前的标识,防止数据重复加载。如下图示:
-
因为预加载机制,有的 fragment 已经初始化完成了,也执行到了 onResume 生命周期方法,但是这时候对用户不可见,所以在 onResume 方法里的 lazyLoad 方法并不会执行,那么这种情况下也就不会执行懒加载操作。
-
不过这个时候,当滑动fragment 对用户可见时,会回调
setUserVisibleHint
生命周期方法,所以我们可以在这里面进行懒加载操作,也就解决了上面说的情况。如下图示:
-
最后,可能有的同学会说,你第一次创建fragment的时候,在 setUserVisibleHint 中调用了 lazyLoad 方法,也在 onResume 中调用了 LazyLoad 方法,你这不是就重复加载数据了吗?
-
说明如下:因为 setUserVisibleHint 方法会优先于 onCreateView 方法执行(如下图示),所以此时 view 还未加载完,那么上面所说的 isViewCreated 标识值为 false ,所以此时 lazyLoad 方法其实并不会执行。因为只有同时满足对用户可见且 view 已经加载完成才去加载数据。
所以问题得以解决。
完整代码
package com.example.myapplication.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.myapplication.R;
/**
* 懒加载写法
*/
public class MyFragment extends Fragment {
private boolean isVisible = false;// 对用户是否可见标识
private boolean isViewCreated = false;// view是否已经加载完成标识
public MyFragment() {
// Required empty public constructor
}
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if (view == null && savedInstanceState == null){
view = inflater.inflate(R.layout.fragment_my, container, false);
}
isViewCreated = true;// view 已经加载
return view;
}
@Override
public void onResume() {
super.onResume();
lazyLoad();
}
/**
* 延迟加载 - 对用户可见且view已经加载完成
*/
private void lazyLoad() {
if(isVisible && isViewCreated){
loadData();
reset();// 恢复标识,防止重复加载
}
}
/**
* 恢复标记 防止重复加载
*/
private void reset(){
isViewCreated = false;
isVisible = false;
}
/**
* 加载数据操作
*/
private void loadData() {
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser){
isVisible = true;// 对用户可见
lazyLoad();
}else {
isVisible = false;// 对用户不可见
}
}
}
上面就是完整的一个懒加载实现的代码,希望对同学们加深理解有帮助。
技术永不眠,我们下期见!