Android 开发中,经常使用到 ViewPager + Fragment 的组合实现多页面的的数据展示。为了保证滑动流畅,ViewPager 引入了预加载机制;ViewPager 通过setOffscreenPageLimt(int limit)
方法来设置预加载页面的数量。
void setOffscreenPageLimt(int limit)
- 官方文档描述该方法将会设置当前页面的两边各自预加载的数量;并且超出这个数量的页面将会被重新创建,最终创建的数量为
2*limit+1
; - 该方法是一个可优化的项;如果我们提前知道展示的 pager 的数量,并且在 Pager 中加入了懒加载机制,调整这个设置保证了分页动画和交互的流畅。如果我们要展示的页面只有3-4 页,我们可以一次性将他们都缓存,这样当用户来回滑动的时候,布局的时间将会大大减少;
- 如果页面布局比较复杂,将
limit
的值尽量设低;默认值为1
, 即便我们将 limit的值设为0 ,它也会被赋为 1,查看源码可知;
但是如果我们的页面有大量的网络请求,特别是预加载多个页面的情况下,就会产生问题: - 并发请求造成堵塞,在网络不良的情况下,无限loading.....
- 一般来说一个网络请求都会用使用到一个异步线程,大量的线程创建、运行、销毁又造成了系统资源的浪费;
因此在预加载的过程中 ,最好先初始化 View,当滑动到对应的页面在执行网络请求布局;为了实现上述的需求,需要借用到 Fragment 的 setUserVisibleHint(boolean isVisibleToUser)
void setUserVisibleHint(boolean isVisibleToUser)
- 告诉系统当前 Fragment 是否对用户可见,默认值为 true , 并且在 Fragment 生命周期内都不会改变;
- 当Fragment 不可见时,应用程序可能将该值设置为 false。系统可以用它来优化操作;
- 该方法优先Fragment 的生命周期调用;而且对生命周期方法的调用不会产生影响;
下面是实现懒加载的基类 BaseFragment
public abstract class BaseFragment extends Fragment {
View view;
protected boolean isPrepared = false;//布局是否加载完毕
protected boolean isVisible = false;//Fragment是否可见
protected boolean isDataInitd = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
System.out.println(this.getClass().getName()+"---isVisibleToUser "+isVisibleToUser);
if(getUserVisibleHint()) {
System.out.println(this.getClass().getName()+"---onVisible");
isVisible =true;
onVisible();
} else {
System.out.println(this.getClass().getName()+"---onInvisible");
isVisible = false;
onInvisible();
}
}
private void onInvisible() {
}
private void onVisible() {
lazyLoad();
}
protected abstract void getData();
protected void lazyLoad() {
System.out.println(this.getClass().getName()+"---lazyLoad() ");
System.out.println(this.getClass().getName()+"---isPrepared " +isPrepared);
System.out.println(this.getClass().getName()+"---isVisible " +isVisible);
System.out.println(this.getClass().getName()+"---isDataInited " +isDataInitd);
if(!isPrepared || !isVisible || isDataInitd) {
System.out.println(this.getClass().getName()+"---我没准备好");
return;
} else {
isDataInitd = true;
System.out.println(this.getClass().getName()+"---执行网络请求");
getData();
}
}
}
下面是继承自BaseFragment 的 AFragment;
public class AFramgent extends BaseFragment {
View view;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater,container,savedInstanceState);
if(view == null) {
view = inflater.inflate(R.layout.a_layout,container,false);
isPrepared = true;
lazyLoad();//第一个可见Fragment 需要调用LazyLoad();其他不用;
}
return view;
}
@Override
protected void getData() {
System.out.println(this.getClass().getName()+"---getData " );
}
}
使用过程中,由于 setUserVisibleHint() 要先于Fragment 的生命周期方法执行,所以要对第一个可见Fragment 做特殊处理,它的网络请求发生在 OnCreateView ()的 LazyLoad() 中,而其他的 Fragment 网络请求发生在调用setUserVisibleHint()中;具体调用如下
2017-02-21_155202.png
网友评论