防止ViewPager和Fragment结合使用时候的数据预加载
不知道你们使用ViewPager和Fragment结合的时候发现一个问题没,如果你的每个Fragment都需要请求网络数据,并且你在请求网络数据的时候会加入进度对话框的加载显示效果,当你显示第一个Fragment的时候,进度对话框并不是在你这个Fragment数据加载完成之后就停止显示了,它会等待ViewPager预加载的Fragment数据也加载完成的时候才会停止显示,即你加载第一个Fragment数据时,进度对话框的显示实际上是两个或者三个的层叠显示。
反正最近我是遇到这种情况了,下面说说我怎么解决的.
ViewPager和Fragment结合使用的时候,有两种适配器可以使用,一个是FragmentStatePagerAdapter,一个是FragmentPagerAdapter。前者在内存中最多会保留三个Fragment实例,也就是说当有Fragment切换的时候,Fragment生命周期会走onDestroyView()-->onDestroy()方法,然后创建会走onCreate()-->onCreateView()方法。但是对于后者,内存中会保留所有创建后的Fragment,也就是说当Fragment切换的时候,生命周期会走onDestroyView()和onCreateView()方法,但是不会走onDestroy()和onCreate()方法。不管是哪一种PagerAdapter,ViewPager都存在预加载Fragment的效果,为了让数据只有在Fragment显示给用户的时候才去加载,我们做了如下几件事情:
1.首先,在Fragment里面有一个方法
public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); }
需要注意的是这个方法会在Fragment的onCreate()方法调用之前就调用,这里我们在里面作如下修改
public void setUserVisibleHint(boolean isVisibleToUser) { if (isVisibleToUser && isVisible()){ initData(); } super.setUserVisibleHint(isVisibleToUser); }
initData()是加载数据的方法,不用管它。这里isVisibleToUser,如果Fragment是显示给用户的,那么这个值是true,isVisible()方法可以判断Fragment的视图是否创建好,对于第一个显示的Fragment,因为isVisibleToUSer是true,但是isVisible()是false,那么在显示第一个Fragment的时候是空白的。但是对于其它的Fragment,因为存在ViewPager的预加载,当显示到Fragment的时候,isVisible()是true,而不是false。所以会在这个方法里面进行加载数据的操作。
2.然后,我们来解决第一个Fragment显示空白的问题,我是在onCreateView()方法里面进行数据的加载操作。然后,我在这个方法里面进行如下的修改
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //... if (getUserVisibleHint()){ initData(); } return inflater.inflate(R.layout.fragment_blank, container, false); }
这里getUserVisibleHint()方法可以判断当前Fragment是否是显示给用户的,对于第一个Fragment,因为不会在setUserVisibleHint()方法里面进行数据加载操作,当走到onCreateView()方法后,会在这里判断,由于getUserVisibleHint()是true,所以会进行数据的加载。然后对于其它的Fragment来说,因为存在预加载的效果,当先走setUserVisibleHint()方法时,由于isVisibleToUser是false,所以不会进行数据的加载,而走完这个方法到达onCreateView()方法时,getUserVisibleHint()返回的是false,所以也不会进行数据的加载,只有当切换到这个Fragment的时候,会去回调setUserVisibleHint()方法,在这个方法里面进行了数据的加载操作。
以上就解决了ViewPager和Fragment结合使用的时候数据的预加载。
3.其实,我觉得上面的做法并不是完美,因为你会发现每次切换到Fragment的时候都会重新加载数据,这样是非常耗流量的。于是乎,我就想了一个办法,在Fragment里面添加了一个long的变量,用来记录Fragment刷新的时间
private long refreshTime = 0;
然后修改setUserVisibleHint()方法,如下所示
public void setUserVisibleHint(boolean isVisibleToUser) { if (isVisibleToUser && isVisible()){ if (refreshTime == 0 ||(refreshTime != 0 && (System.currentTimeMillis()-refreshTime) > 30 * 60 * 1000)) { initData(); } } super.setUserVisibleHint(isVisibleToUser); }
即如果这个Fragment的View视图没有被销毁的时候,只有当数据的时效性超过30min后再次切换到这个Fragment才会进行数据的加载。
4.在每次进行数据加载操作的时候对这个时间刷新,在每次View视图被重新创建的时候将时间置为0,如下所示
private void initData(){ refreshTime=System.currentTimeMillis();}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { refreshTime = 0; //....... }
好了,以上是关于我如何解决ViewPager和Fragment结合使用时候的数据预加载问题。其实我们还可以进行优化,对每个Fragment获取到的网络数据(一般是json)进行缓存,当每次切换的时候,先去加载本地的json数据进行展示,再去判断当前时间和这个json被缓存的时间是否超过一定的值,如果超过,再进行网络请求刷新数据。我觉得这样会更好。谢谢~晚安了,各位!
防止ViewPager和Fragment结合使用时候的数据预加载的更多相关文章
- ViewPager+Fragment取消预加载(延迟加载)(转)
原文:http://www.2cto.com/kf/201501/368954.html 在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragmen ...
- viewpager和fragment预加载的解决
在使用Viewpager和fragment处理中会出现预加载的问题,最近看别人的代码,终于找到了一个很好的处理方法 能有效的解决预加载的问题,在fragment都继承一个重写setUserVisibl ...
- Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53205878本文出自[DylanAndroid的博客] Android中Vie ...
- ViewPager+Fragment取消预加载(延迟加载)
在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方.例如你在ViewPager中添加了三个Fragment,当加载V ...
- ViewPager防止Fragment销毁以及取消Fragment的预加载
存在的问题 1. 默认情况下,ViewPager会根据setOffscreenPageLimit()方法设置的大小,自动预加载2. 还是根据setOffscreenPageLimit()方法设置的大小 ...
- android Viewpager取消预加载及Fragment方法的学习
1.在使用ViewPager嵌套Fragment的时候,由于VIewPager的几个Adapter的设置来说,都会有一定的预加载.通过设置setOffscreenPageLimit(int numbe ...
- 巧力避免ViewPager的预加载数据,Tablayout+Fragment+viewPager
问题描述 最近在进行一个项目的开发,其中使用到了Tablayout+Fragment+viewPager来搭建一个基本的框架,从而出现了设置数据适配器的时候,item的位置错乱问题.我打印log日志的 ...
- ViewPager的刷新、限制预加载、缓存所有
[框架]: 公共部分:左侧菜单.TitleBar.RadioGroup(3个RadioButton:X.Y.Z) 选择X页面:指示器+ViewPager [要达成的效果]: (1)左侧选择A,进入X页 ...
- 关于禁止ViewPager预加载问题【转】
转自:http://blog.csdn.net/qq_21898059/article/details/51453938#comments 我最近上班又遇到一个小难题了,就是如题所述:ViewPage ...
随机推荐
- MongoDB 副本集的原理、搭建、应用
概念: 在了解了这篇文章之后,可以进行该篇文章的说明和测试.MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组 ...
- metro中stream转IRandomAccessStream
下面的例子是从zip压缩文件解压出jpg文件流,再显示出来. StorageFile zip = await KnownFolders.PicturesLibrary.GetFileAsync(&qu ...
- Django~Models1
不用数据库不用Models 省却 --------------- startapp urls +链接 view以下 ---------------- 添加Model 在project/settings ...
- Urllib2 总结
Urllib2 总结 介绍 Urllib2是用于获取URLs(统一资源定位符)的一个Python模块.它以urlopen函数的形式提供了非常简单的接口.能够使用各种不同的协议来获取网址.它还提供一个稍 ...
- 【leetcode】Reverse Nodes in k-Group (hard)☆
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If ...
- UVA 11827 Maximum GCD
F - Maximum GCD Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Given the ...
- IOS - 首次启动程序出现的画面介绍
1.在appdelegate.m中找到 “application:didFinishLaunchingWithOptions:” 通过NSUserDefaults 来进行判断 if (![[NSUse ...
- [Android Pro] Android以root起一个process[shell脚本的方法]
reference to : http://***/Article/11768 有时候我们写的app要用uid=0的方式启动一个process,framework层和app层是做不到的,只有通过写脚 ...
- [Android Pro] Android保存图片到系统图库
http://stormzhang.github.io/android/2014/07/24/android-save-image-to-gallery/ http://blog.csdn.net/x ...
- 3ds max画曲线 设置摄像机的起始位置
参考 http://www.3dmax8.com/3dmax/2013/0916/5661.html 如果想创建曲线段,可以在单击下一个点时按住鼠标不放,继续拖曳,再拖到另一个点上,单击鼠标右键,即可 ...