懒加载介绍
所谓的懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据。
这样可以提高所属Activity的初始化速度,也可以为用户节省流量,而这种懒加载的方式也已经/正在被诸多APP所采用。
Fragment为我们提供了一个方法setUserVisibleHint(boolean isVisibleToUser)
,其中的参数isVisibleToUser
就是表示该Fragment的UI对于用户是否可见。
setUserVisibleHint(boolean isVisibleToUser)
方法会多次回调,而且可能会在onCreateView()
方法执行完毕之前回调。如果isVisibleToUser==true,然后进行数据加载和控件数据填充,但是onCreateView()
方法并未执行完毕,此时就会出现NullPointerException空指针异常。
基于以上原因,我们进行数据懒加载的时机需要满足两个条件:
onCreateView()
方法执行完毕setUserVisibleHint(boolean isVisibleToUser)
方法返回true
完整代码
public class LazyFragment extends Fragment {
private static final String TAG = "LazyFragment";
private static final String NAME = "name";
private String titlename ;
//Fragment的View加载完毕的标记
private boolean isViewCreated;
//Fragment对用户可见的标记
private boolean isUiVisible;
private Unbinder unbinder;
@BindView(R.id.swipe)
SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.tv_title)
TextView tvTitle;
public static LazyFragment newInstance(String name) {
LazyFragment fragment = new LazyFragment();
Bundle bundle = new Bundle();
bundle.putString(NAME, name);
fragment.setArguments(bundle);
return fragment;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
Log.i(TAG, "setUserVisibleHint -- " + isVisibleToUser);
if (isVisibleToUser) {
isUiVisible = true;
lazyLoad();
} else {
isUiVisible = false;
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
titlename = getArguments().getString(NAME);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_lazy, container, false);
unbinder = ButterKnife.bind(this, v);
tvTitle.setText(titlename);
return v;
}
//调用此方法代表 onCreateView() 方法执行完毕
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.i(TAG, "onViewCreated");
isViewCreated = true;
lazyLoad();
}
private void lazyLoad() {
//这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,
// 必须确保onCreateView加载完毕且页面可见,才加载数据
if (isViewCreated && isUiVisible) {
loadData();
//数据加载完毕,恢复标记,防止重复加载
isViewCreated = false;
isUiVisible = false;
}
}
private void loadData() {
Log.i(TAG, "loadData");
//模拟加载网络数据
swipeRefreshLayout.setRefreshing(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
}, 2000);
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.i(TAG, "onDestroyView");
unbinder.unbind();
//页面销毁,恢复标记
isViewCreated = false;
isUiVisible = false;
}
}
效果