Volley缓存分析

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

     我们知道了Volley内部的缓存策略,那么Volley的硬盘缓存的缓存目录在哪里呢?Volley缓存哪些数据,是图片还是json还是普通字符串数据?

关于Volley具体源码分析可参考:Volley源码分析


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


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加载图片是一样的,只不过它对网络请求的生命周期进行了更好的管理。

除此之外NetworkImageView可用于解决listview异步加载大量图片乱序的情况:

如果有新的图片加载请求,NetworkImageView调用cancelRequest()就会把旧的加载请求取消掉,只要是取消掉的请求,就绝对不会进行回调,既然不会回调,那么也就不会回到NetworkImageView当中,自然也就不会出现乱序的情况了。需要注意的是,Volley只是保证取消掉的请求不会进行回调而已,但并没有说可以中断任何请求。由此可见即使是Volley也无法做到中断一个正在执行的线程,如果有一个线程正在执行,Volley只会保证在它执行完之后不会进行回调,但在调用者看来,就好像是这个请求就被取消掉了一样。

另外还可使用findViewWithTag来解决这个问题,由于ListView中的ImageView控件都是重用的,移出屏幕的控件很快会被进入屏幕的图片重新利用起来,那么getView()方法就会再次得到执行,而在getView()方法中会为这个ImageView控件设置新的Tag,这样老的Tag就会被覆盖掉,于是这时再调用findVIewWithTag()方法并传入老的Tag,就只能得到null了,而我们判断只有ImageView不等于null的时候才会设置图片,这样图片乱序的问题也就不存在了。

Volley的缓存机制

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

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

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

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

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值