共计 1796 个字符,预计需要花费 5 分钟才能阅读完成。
简述:
渐渐的在开发道路上更注重 App 的性能,数据的预加载的处理。在日常开发 APP,一个 Activity 里面有可能会是有 Viewpager 与多个 Fragment 来进行组合,而如果每个 Fragment 都需要通过网络加载数据,或加载本地缓存。如果当前 Activity 创建的时候就需要初始化大量的资源,需要网络加载,从服务器 loding。这样的结果,我们也不会同意。那如何才能更好的处理这个问题呢?那就需要我们开发人员自定义实现 Fragment 数据的缓加载。
答案:在 Fragment 里的 setUserVisibleHint 这个方法里
该方法用于告诉系统,这个 Fragment 的 UI 是否是可见的。所以我们只需要继承 Fragment 并重写该方法,即可实现在 fragment 可见时才进行数据加载操作,即 Fragment 的懒加载。
public abstract class LazyFragment extends Fragment {
protected boolean isVisible;
/**
* 在这里实现 Fragment 数据的缓加载.
* @param isVisibleToUser
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
protected void onVisible(){
lazyLoad();
}
protected abstract void lazyLoad();
protected void onInvisible(){}
}
在 LazyFragment,我增加了三个方法,一个是 onVisiable,即 fragment 被设置为可见时调用,一个是 onInvisible,即 fragment 被设置为不可见时调用。另外再写了一个 lazyLoad 的抽象方法,该方法在 onVisible 里面调用。你可能会想,为什么不在 getUserVisibleHint 里面就直接调用呢?
我这么写是为了代码的复用。因为在 fragment 中,我们还需要创建视图(onCreateView() 方法),可能还需要在它不可见时就进行其他小量的初始化操作(比如初始化需要通过 AIDL 调用的远程服务)等。而 setUserVisibleHint 是在 onCreateView 之前调用的,那么在视图未初始化的时候,在 lazyLoad 当中就使用的话,就会有空指针的异常。而把 lazyLoad 抽离成一个方法,那么它的子类就可以这样做:
public class OpenResultFragment extends LazyFragment{
// 标志位,标志已经初始化完成。
private boolean isPrepared;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(LOG_TAG, “onCreateView”);
View view = inflater.inflate(R.layout.fragment_open_result, container, false);
//XXX 初始化 view 的各控件
isPrepared = true;
lazyLoad();
return view;
}
@Override
protected void lazyLoad() {
if(!isPrepared || !isVisible) {
return;
}
// 填充各控件的数据
}
} 在上面的类当中,我们增加了一个标志位 isPrepared,用于标志是否初始化完成。然后在我们所需要的初始化操作完成之后调用,如上面的例子当中,在初始化 view 之后,设置 isPrepared 为 true,同时调用 lazyLoad() 方法。而在 lazyLoad() 当中,判断 isPrepared 和 isVisible 只要有一个不为 true 就不往下执行。也就是仅当初始化完成,并且可见的时候才继续加载,这样的避免了未初始化完成就使用而带来的问题。