1.原因
在开发过程中我们会遇到Viewpager嵌套Fragment的情况,这时如果每个Fragment中都含有耗时操作(如网络请求等),由于Viewpager有预加载功能,此时无论Fragment是否可见,都已被创建。这样会造成用户的流量消耗、耗时等。
2.setUserVisibleHint()方法被移除
一般的做法是结合Fragment 有一个非生命周期的
setUserVisibleHint(boolean isVisibleToUser)
回调方法来完成懒加载功能,但是在
androidx.fragment.app.FragmentPagerAdapter
中此方法被移除了。下面是开发者文档中提到的
image
3.生命周期
- 1)创建Fragment
onAttach() —> onCreate() —> onCreateView() —> onActivityCreated() —> onStart() —> onResume()
- 2)从桌面回到Fragment / 解锁
onStart() —> onResume()
- 3)切换回本身的Fragment
onCreateView() —> onActivityCreated() —> onStart() —> onResume()
所以我们可以在OnResume中来判断此Fragment是否对用户可见来完成懒加载
public abstract class BaseFragment<V extends ViewDataBinding> extends Fragment{
protected V binding;
private View mView;
private boolean isViewCreated; // 界面是否已创建完成
private boolean isVisibleToUser; // 是否对用户可见
private boolean isDataLoaded; // 数据是否已请求, isNeedReload()返回false的时起作用
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//避免重复创建View
if (mView == null){
binding = DataBindingUtil.inflate(inflater, initContentView(inflater, container, savedInstanceState), container, false);
mView = binding.getRoot();
isViewCreated = true;
tryLoadData();
}else {
ViewGroup parent = (ViewGroup) mView.getParent();
if (parent != null){
parent.removeView(mView);
}
}
return mView;
}
public abstract void initData();
public abstract int initContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
/**
* fragment再次可见时,是否重新请求数据,默认为flase则只请求一次数据
*
* @return
*/
protected boolean isNeedReload() {
return false;
}
@Override
public void onResume() {
super.onResume();
isVisibleToUser = true;
tryLoadData();
}
private void tryLoadData() {
if (isViewCreated && isVisibleToUser && !isDataLoaded) {
initData();
isDataLoaded = true;
}
}
}
网友评论