最近写一个Demo的时候用到了Fragment+ViewPager,所以发现了一些坑。
记录下来,给遇到同样问题的人做个参考,也为了避免以后遇到同样的坑。
- Fragment中的数据加载
因为ViewPager的运行机制,它会预加载当前页面的前后的两个页面,当移动到当前页面后的第三个页面,而会销毁那个页面,而如果我们在Fragment中有很多的耗时操作,比如网络请求,就会造成一些用户出现数据加载延迟和页面卡顿的情况,用户体验非常不好。所以为了避免预加载的情况发生,我们就需要用到Fragment的懒加载,看代码:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.d(TAG, "setUserVisibleHint: ");
if (isVisibleToUser) { // 如果页面呈现在用户面前
//这里执行耗时操作
}
}
重写Fragment的setUserVisibleHint()方法,因为我们通过打印日志发现,这个方法会在onCreat()和onCreatView()之前调用,而且这个方法中的变量isVisibleToUser就正好反应的是页面是否呈现给用户,当某页面是当前页面的相邻页面,这个方法也会调用,不过isVisibleToUser是false,所以我们可以在这个方法中,根据isVisibleToUser的值判断是否开始执行耗时操作。
另外为了避免重复加载数据,即当Fragment被销毁之后又显示给用户的时候,重复加载数据,如果这时候有网络请求,就会重复浪费用户的流量,是很不友好的,说再多不如看代码:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.d(TAG, "setUserVisibleHint: ");
if (isVisibleToUser && !isGotData) {
getImageurl(); // 这里面有初始化试图的操作initView()
isGotData = true;
}else if(!isInitView && isVisibleToUser) {
initView();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
isInitView = false;
}
这里的isGotData是是否已经加载过数据的标志,isInitView是是否已经初始化过视图的标志,两个结合避免初始化数据的操作在第一个if判断里面,试图被销毁后就不会再次加载的尴尬!还要记住在onDestroyView中将标志位重置一下,标志此时视图已经被销毁,需要重新加载。不要在onDestroy中重置!X 3,重要的事说三遍,因为这里ViewPager销毁Fragment调用的是onDestroyView,而不是onDestroy。
setUserVisibleHint中获取上下文Context为空
因为是Fragment里面,我们常会用getActivity()、getContext()来获取context,但是,因为这个方法是在onCreate()和onCreateView()之前调用的,所以这个时候获取上下文肯定是为空的,只有等后两个方法调用之后才能获取到上下文,可以加入标志位,在这之后才去获取上下文,也可以避免在这里面获取上下文。
暂时遇到这么多,以后继续分享开发过程中遇到的坑,让自学的我们少走些弯路。
因为个人水平有限,如果以上有什么错误的地方,欢迎大家批评指正!