Fragment的懒加载与生命周期详解
什么是懒加载
在Android中经常用到ViewPager + Fragment来加载数据,但是ViewPager有预加载的功能,当其他页面存在耗时操作,页面就会出现不流畅。而懒加载就是为了解决这一问题。懒加载其实就是延时加载,即当对象需要用到(对视图可见)的时候才会加载。通过这种“懒”方法提升用户体验。
了解Fragment的生命周期
要想实现Fragment的懒加载,首先要彻底搞清楚Fragment的生命周期。
onAttach
当Fragement首次附加到其活动时调用。
onCreate
系统创建Fragement的时候回调,在其中实例化一些变量,这些变量主要是:当你回调onPause、onStop的时候(即暂停,停止),你想保存的数据如果我们要为fragment启动一个后台线程,可以考虑将代码放于这里。
onCreateView
给当前的Fragement绘制ui布局,可以使用线程更新UI。这里一般都先判断是否为null,避免重复加载。
if (view == null) {
view = LayoutInflater.from(getContext()).inflate(R.layout.fragment_my, null);
textView = view.findViewById(R.id.textView);
}
onActivityCreated
当Fragement被所在的Activity启动完成后回调该方法。官方的话是: 当Activity中的onCreate方法执行完后调用。
从官方的话可以看出,所以在onActivityCreated调用之前activity的onCreate可能还没有完成,所以不能在fragment的onCreateView中进行与activity有交互的UI操作。
所以:可以在这个方法中初始化那些必须要依赖父Activity或Fragment的元素才能初始化的元素。(例如ListView)
onStart
启动Fragement 启动时回调,此时Fragement可见。
onResume
Fragement 进入前台,可获取焦点。
onPause
离开这个Fragement,仍然可见。
onStop
Fragement不可见。
onDestroyView
销毁与Fragment有关的视图。
onDestroy
销毁Fragment对象。
onDetach
Fragment和Activity解除关联。
懒加载的实现和封装
要实现懒加载,还得知道一个方法:setUserVisibleHint
这个方法的回调在onAttach之前,用来判断当前Fragment是否对用户可见,并且每次切换都会回调。所以我们可以定义两个标志位变量:
private boolean isViewInit; // view是否已经加载完成
private boolean isVisible; // 是否可见
在setUserVisibleHint中对isVisibleToUser作逻辑判断,并改变标志位
// fragment视图是否对用户可见
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
isVisible = true;
lazyLoad();
}else {
isVisible = false;
}
}
在onActivityCreated改变标志位,开始加载
// 懒加载逻辑
public void lazyLoad() {
if (!isViewInit || !isVisible) {// view加载完成&可见
return;
}
initData();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInit = true; //设置标志位,view表示初始化完成
lazyLoad(); //懒加载
}
private void initData() {
//数据初始化
}
封装的实现:
每写一个Fragment,都还要写一遍逻辑,程序员要的是代码精简。所以抽象封装是个好东西。用抽象类继承Fragment,实现上述的所有方法,将initData改成抽象方法。下次需要懒加载的时候就可以直接继承这个抽象类就好。
博主特地写了一个Demo打印activity和fragment的生命周期,其中也包括懒加载的实现和选项卡的嵌套。Demo地址