Volley网络框架完全解析(缓存篇)

在上一篇中讲完了Volley框架怎么使用,那么这篇就来讲讲Volley框架的缓存机制

我们看Volley内部源码发现:

Volley框架内部自己处理了DiskBasedCache硬盘缓存,但是没有处理LruCache内存缓存,因为一般在处理图片的问题上才更多的用到LruCache缓存,但是它提供了一个ImageCache接口供我们自己实现,该接口默认需要实现两个方法:getBitmap(String key)和putBitmap(String key, Bitmap bitmap),由此可见,这就是从缓存中拿数据和存入数据的两个方法,我们完全可以使用LruCache来实现内存缓存

好了,我们知道了Volley内部的缓存策略,那么Volley的硬盘缓存的缓存目录在哪里呢?Volley缓存哪些数据,是图片还是json还是普通字符串数据?带着这些问题,我们首先就是看源码。

Volley的缓存目录

我们从源码中发现创建一个请求队列的同时,会同时创建Volley的缓存目录和DiskBasedCache缓存对象,我们可以得知Volley的缓存目录就是在我们应用内置的cacheDir目录下的volley文件夹中,然后把这个目录用作DiskBasedCache硬盘缓存的目录,源码如下:

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        File cacheDir = new File(context.getCacheDir(), "volley");
        ...
        RequestQueue queue1 = new RequestQueue(new DiskBasedCache(cacheDir), network1);
        queue1.start();
        return queue1;
    }

于是,我们打开文件管理器发现缓存目录确实是在里面:

Volley缓存的数据

Volley缓存的数据其实包括字符串数据、json数据、图片等,它可以缓存我们请求得到的数据

Volley加载图片的方案

Volley为我们提供了多种加载图片的方法:

1、使用ImageRequest

2、使用ImageLoader

3、使用ImageLoader+NetworkImageView

它们的使用我在上一篇Volley的使用篇就说过了,现在主要讲讲它们分别适合的运用场景和原理

1、使用ImageRequest,适用在图片数量不多的情况下,并且它本身内部可以处理图片的压缩和图片质量的配置,构造方法为:

/**
* @url 请求url
* @listener 请求成功回调的接口
* @maxWidth 图片最大的宽度(如果超过则Volley会对图片进行压缩,如果为0则不压缩)
* @maxHeight 图片最大的高度
* @decodeConfig 图片的配置
* @errorListener 请求失败回调的接口
*/
public ImageRequest(String url, Listener<Bitmap> listener, int maxWidth, int maxHeight, Config decodeConfig, ErrorListener errorListener)

2、使用ImageLoader,适用在图片数量多的情况下,同时它使用get()方法在加载图片时候根据情况也可以对图片进行压缩处理,get()方法参数为:

/**
* @requestUrl - 请求url
* @listener - ImageLoader.ImageListener的监听对象
* @maxWidth - 图片的最大高度,如果超过则会压缩,为0则不压缩
* @maxHeight
*/
public ImageLoader.ImageContainer get(String requestUrl, ImageLoader.ImageListener listener, int maxWidth, int maxHeight)

ImageLoader构造方法为:

/**
*@queue 请求队列
*@imageCache 实现了ImageCache接口的缓存对象
*/
public ImageLoader(RequestQueue queue, ImageLoader.ImageCache imageCache)

3、使用ImageLoader+NetworkImageView,在上一个方法中,我们同样也是使用了ImageLoader,不过这个方法我们是使用Volley提供的NetworkImageView来显示图片的,为什么使用它呢?因为它会自动管理本身请求的生命周期,当NetworkImageView退出屏幕时或者Activity退出时候,它会自动取消网络请求,从而节约资源。同样,该方法适合用在图片数量多的情况下,同时它也有对图片压缩的处理方法,就是通过在layout.xml布局文件中设置它的宽高,加载图片的时候会根据图片的大小和设定的宽高进行压缩的。

<com.android.volley.toolbox.NetworkImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    ...
    />

那为什么NetworkImageView可以直接使用setImageUrl(url, mImageLoader);方法直接设置图片呢?因为这个方法内部是通过调用ImageLoader中的get()方法来请求得到图片的,所以原理和ImageLoader加载图片是一样的,只不过它对网络请求的生命周期进行了更好的管理。

【总结】:所以,综上所述,我们可以更据不同的需求来采取不同的方法,可见Volley对图片的加载策略还是非常的强大的。

Volley的缓存机制

Volley缓存到底是怎样的呢?首先,我们通过一个实例来看,这个实例中我使用JsonObjectRequest来请求json数据,使用ImageRequest来加载三张图片,使用ImageLoader+NetworkImageView来加载另外三张图片,我们运行一下可以看到这个效果:

可以看到图片和json数据都加载出来了,那么这些数据是不是都会缓存到cacheDir->volley目录下呢?当然会了,因为Volley默认情况下都会保存缓存数据到volley缓存目录下的,我们打开volley目录:

发现确实存在七个缓存文件,说明了我们的json数据也缓存了,其中以“-993813455”开头的文件就是我们图片的缓存文件,而另外一个则是json数据字符串的缓存文件,那么这些缓存文件的内容是什么呢?我们首先打开其中一个图片缓存文件,内容如下:

我们从文件内容中很难看懂里面的大部分内容,不过开头的那部分我们还是能看懂的,上面我标记了的三个表示的内容分别是:图片请求的url地址、图片的名称、图片的大小。后面那部分乱码的内容其实就是图片的内容。

我们再打开缓存json数据的那个文件,内容如下:

该文件的内容比较少,我们也比较容易看懂,上面我标记的三个表示的内容分别是:json数据请求的url地址、内容的类型、json数据的内容。我们可以看到它把json数据的内容保存到缓存文件中,虽然我们很难看懂其中的内容,不过在从缓存中取出内容时候它将会自动转码成正常的内容显示出来。

好了,Volley的缓存文件的内容已经讲清楚了,那么,Volley在什么时候使用这些缓存呢?

我们首先在刚刚的前提下,然后把网断了,看看它还会不会加载数据:

我们可以看到,断网情况下,图片都加载出来了,而json字符串数据却没有加载出来,为什么呢?

首先我来回答为什么图片可以加载出来:

因为Volley内部本身就处理了数据的硬盘缓存,通过Volley请求的数据默认情况下都会缓存到volley缓存目录下,所以,正因为它内部具有硬盘缓存,使得Volley在请求网络数据时候首先会查找volley缓存目录下是否有该缓存文件,如果有则从缓存中取出,没有则通过网络请求获取数据。那么Volley是怎么判断该缓存文件的数据是否是我们请求需要的数据呢?答案是通过url来做判断,我们刚刚不是打开了缓存文件么,不管是json类型的还是图片的缓存文件,开头部分都是该数据的url,所以就是通过url做判断。

那为什么json字符串数据加载不出来呢?

我们刚刚说了Volley请求网络数据时候都会先从缓存中找,当然json字符串数据也一样,不过,这里我要引入一个概念,就是Volley从缓存文件中拿取数据的时候,都会先判断这个缓存文件的ttl(“过期时间”)是否过期,这个ttl的值是由缓存中的MaxAge的值来计算的,而MaxAge值又是从Response中的cache-control得到的,我们可以在上面的图片缓存文件的第四行可以看到图片的缓存文件有maxage而且有值,而json数据的缓存文件则没有,所以它的maxage为0,从而一直都处于过期状态,所以Volley就不会从这个json缓存文件中取数据而是需要通过网络请求获取数据。(如果不想让字符串类型数据过期,我们可以通过控制服务器传回来的Header信息中CacheControl的信息来控制)

由于加载图片我们用的是ImageLoader请求获取图片,自然的需要实现ImageCache接口了,所以,在图片加载时候则是首先判断ImageCache中有没有该图片,再判断缓存目录下是否有该缓存文件,如果都没有最后则是通过网络请求获取,否则将会从缓存中取。

Volley缓存-手动的得到缓存数据和清理缓存数据

得到对应url的缓存

我们可以通过RequestQueue.getCache()来得到Volley中的Cache对象,然后通过Cache.get(url)来得到缓存的Entry,通过Entry我们可以得到这个缓存实体的相关信息:

其中Entry.data就是得到该缓存文件的字节数组,通过它我们可以转化为我们需要的内容。

一个获取缓存文件字符串数据的示例如下:

if(mRequestQueue.getCache().get(url)!=null){
    mTextView.setText(new String(mRequestQueue.getCache().get(url).data).toString());
}

清除一个缓存文件

我们可以通过Cache.remove(String url)来移除对应url的缓存文件,如:

mRequestQueue.getCache().remove(url);

clear()清空缓存

我们可以通过调用Cache.clear();来清空缓存,如下:

mRequestQueue.getCache().clear();

当我们调用它清空缓存,volley目录下的缓存文件全部会被清除,如:

综上所述,我们可以在字符串数据过期的情况下,我们先判断当前网络是否连接,如果没有连接,则手动的获取字符串数据的缓存数据,这样可以很好的解决没有网络连接情况下没数据显示的问题。

如:

StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                mTextView.setText(s);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                //使用缓存数据
                if(mRequestQueue.getCache().get(url)!=null){
                    mTextView.setText(new String(mRequestQueue.getCache().get(url).data).toString());
                }
            }
        });

这样在没网络连接的情况下,将会调用onErrorResponse()方法,此时我们可以手动获取缓存中的数据来显示。

好了,Volley的缓存就全部讲完了,下一篇Volley实战篇之获取大量的网络图片。

版权声明:本文为博主原创文章,未经博主允许不得转载。转载注明出处:http://blog.csdn.net/u010687392

时间: 2024-08-26 02:12:05

Volley网络框架完全解析(缓存篇)的相关文章

Volley网络框架完全解析(实战篇)

好了,今天就通过一个瀑布流demo,来使用Volley框架请求网络图片. 前言: 我们使用NetworkImageView显示图片: 1.因为该控件可以自动的管理好请求的生命周期,当与父控件detach或者它移出屏幕时可以自动取消网络请求 2.该控件会根据我们所设置的NetworkImageView宽高来进行图片的压缩 3.该控件可以设置默认状态下显示的图片,可以设置在请求失败时候显示的图片 还用了ImageLoader来加载图片,使用ImageCache缓存来防止程序OOM,由于Volley自

Volley网络框架的使用

Volley的特点: 使用网络通信更快.更简单 Get/Post网络请求网络图像的高效率异步请求 可以对网络请求的优先级进行排序处理 可以进行网络请求的缓存 可以取消多级别请求 可以和Activity生命周期联动 Volley的使用: 1.Volley网络请求队列建立与取消队列请求 使用Volley需要建立一个全局的请求队列,这样就可以讲一个请求加入到这个全局队列中,并管理整个app的所有请求. 2.Volley的Get和Post请求方式的使用 Volley的Get和Post请求方式其实是对An

jQuery2.x源码解析(缓存篇)

缓存是jQuery中的又一核心设计,jQuery自身的很多东西都依赖于缓存,比如事件.一些中间变量.动画等.同时他还为用户提供接口了使用缓存的接口,方便用户在元素节点上保存自己的数据,并且帮助用户解决直接把数据保存到DOM元素是可能引起的内存泄漏.命名冲突等问题. 同时,html5提出了一种通过属性缓存元素数据的功能,就是data-*属性,他可以以字符串的形式保存数据,并且不会和元素固有属性冲突.jQuery的缓存提供了访问data-*的接口,与html5标准结合更加紧密,更加规范. 提问:jQ

教你写Android网络框架之请求配置与Response缓存

前言 在教你写Android网络框架的前三篇文章中,我们从基本结构到代码实现,剖析了一个简单的网络框架应该是怎样运作的,以及在面对各式各样的需求时应该如何对代码做出处理,在深入了解网络框架的同时学习到一些简单的面向对象设计原则.正如第一篇博文所说,SimpleNet框架参照的是Volley实现,甚至有一些类名也是一样的.我们的目标并不是要重新发明轮子,而是以学习轮子制作的过程来达到提升自我的目的.SimpleNet只是一个简单的网络框架实现,没有经过严格的测试以及市场检验,不建议大家在项目中使用

ym—— Android网络框架Volley(体验篇)

<a target=_blank href="https://android.googlesource.com/platform/frameworks/volley" style="font-family: Arial, Helvetica, sans-serif; box-sizing: border-box; background-image: initial; background-attachment: initial; background-color: rg

Android volley 解析(四)之缓存篇

这是 volley 的第四篇 blog 了,写完这篇,volley 的大部分用法也都算写了一遍,所以暂时不会写 volley 的文章了,如果想看我前面写的文章,可以点这里 Android volley 解析(三)之文件上传篇 为什么要用缓存 我们知道,当客户端在请求网络数据的时候,是需要消耗流量的,特别是对于移动端用户来说,对于流量的控制要求很高.所以在做网络请求的时候,如果对数据更新要求不是特别高,往往都会用到缓存机制,一方面能减少对服务端的请求,控制流量:另一方面,当客户端在没有网络的情况下

ym—— Android网络框架Volley(实战篇)

转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持. 之前讲了ym-- Android网络框架Volley(体验篇),大家应该了解了volley的使用,接下来我们要看看怎样把volley使用到实战项目里面,我们先考虑下一些问题: 从上一篇来看 mQueue 仅仅须要一个对象就可以,new RequestQueue对象对资源一种浪费,我们应该在application.以及能够把取消请求的方法也在application进行统一管理,看下面代

怎样使用ListView实现一个带有网络请求,解析,分页,缓存的公共的List页面来大大的提高工作效率

在寻常的开发中常常会有非常多列表页面.每做一个列表页就须要创建这个布局文件那个Adapter适配器文件等等一大堆与之相关的附属的不必要的冗余文件. 假设版本号更新迭代比較频繁,如此以往,就会使项目project变得无比庞大臃肿. 假设看过这篇文章或者在使用过这样的方式之后呢,全部的工作都能够被压缩成仅仅有两个文件,一个JAVA文件一个XML布局文件. 并且代码还少少的. 咱们来看看实际情况: 寻常的一个列表页面的生成须要下面文件: 一个Activity文件.有时候可能还会忘记注冊 一个包括上下拉

Android Volley框架完全解析

2013年Google I/O大会上推出了一个新的网络通信框架--Volley.Volley可是说是把AsyncHttpClient和Universal-Image-Loader的优点集于了一身,既可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片.除了简单易用之外,Volley在性能方面也进行了大幅度的调整,它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如