ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的。但因为源码中没有提供磁盘缓存的设置,所以咱们还需要去源码中进行修改,让我们可以更加自如的设定是否进行磁盘缓存。

一、添加对磁盘缓存的控制

我们默默的打开源码,添加如下代码:

  1. private boolean mShouldCache = true;
  2. /**
  3. * Set whether or not responses to this request should be cached(Disk Cache).
  4. *
  5. * @return This Request object to allow for chaining.
  6. */
  7. public void setShouldCache(boolean shouldCache) {
  8. mShouldCache = shouldCache;
  9. }
  10.  
  11. /**
  12. * Returns true if responses to this request should be cached.
  13. */
  14. public final boolean shouldCache() {
  15. return mShouldCache;
  16. }

定位到get方法

  1. public ImageContainer get(String requestUrl, ImageListener imageListener,
  2. int maxWidth, int maxHeight)

找到初始化Request<Bitmap>的地方。

  1. public ImageContainer get(String requestUrl, ImageListener imageListener,
  2. int maxWidth, int maxHeight) {
  3. // only fulfill requests that were initiated from the main thread.
  4. throwIfNotOnMainThread();
  5.  
  6. final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);
  7.  
  8. // Try to look up the request in the cache of remote images.
  9. Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
  10. if (cachedBitmap != null) {
  11. // Return the cached bitmap.
  12. ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null);
  13. imageListener.onResponse(container, true);
  14. return container;
  15. }
  16.  
  17. // The bitmap did not exist in the cache, fetch it!
  18. ImageContainer imageContainer =
  19. new ImageContainer(null, requestUrl, cacheKey, imageListener);
  20.  
  21. // Update the caller to let them know that they should use the default bitmap.
  22. imageListener.onResponse(imageContainer, true);
  23.  
  24. // Check to see if a request is already in-flight.
  25. BatchedImageRequest request = mInFlightRequests.get(cacheKey);
  26. if (request != null) {
  27. // If it is, add this request to the list of listeners.
  28. request.addContainer(imageContainer);
  29. return imageContainer;
  30. }
  31.  
  32. // The request is not already in flight. Send the new request to the network and
  33. // track it.
  34. Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, cacheKey);
  35. mRequestQueue.add(newRequest);
  36. mInFlightRequests.put(cacheKey,
  37. new BatchedImageRequest(newRequest, imageContainer));
  38. return imageContainer;
  39. }

把红色代码中间添加:newRequest.setShouldCache(mShouldCache);最终效果如下:

  1.      // The request is not already in flight. Send the new request to the network and
  2. // track it.
  3. Request<Bitmap> newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, cacheKey);
  4. newRequest.setShouldCache(mShouldCache);
  5. mRequestQueue.add(newRequest);

二、ImageLoader

  1. /**
  2. * Constructs a new ImageLoader.
  3. * @param queue The RequestQueue to use for making image requests.
  4. * @param imageCache The cache to use as an L1 cache.
  5. */
  6. public ImageLoader(RequestQueue queue, ImageCache imageCache) {
  7. mRequestQueue = queue;
  8. mCache = imageCache;
  9. }

初始化要传入两个参数:①RequestQueue对象;②ImageCache对象(不能传null!!!!)

RequestQueue这个我就不多说了,之前的文章已经讲解过了,下面来说说ImageCache这个对象。

2.1 建立ImageCache对象来实现内存缓存

ImageCache是一个图片的内存缓存对象,源码中叫做L1缓存,其实缓存分为L1、L2两种,L1就是所谓的内存缓存,将展示过的图片放入内存中进行缓存,L2就是磁盘缓存,如果这个图片下载完成,它可以被存放到磁盘中,在没有网络的时候就可以调出来使用了。

为了简单我先空实现ImageCache接口,产生一个MyImageCache对象

  1. class MyImageCache implements ImageCache {
  2.  
  3. @Override
  4. public Bitmap getBitmap(String url) {
  5. return null;
  6. }
  7.  
  8. @Override
  9. public void putBitmap(String url, Bitmap bitmap) {
  10. }
  11. }

这个接口提供的方法简单明了,今后我们可以用自己的内存缓存来完善这个类,当前getBitmap返回的是null,说明这个内存缓存没啥用处,和没缓存一样。

2.2 实现加载网络图片

  1. ImageLoader imageLoader = new ImageLoader(mQueue, new MyImageCache());
  2. ImageListener listener = ImageLoader.getImageListener(iv, R.drawable.default_photo, R.drawable.error_photo);
  3. imageLoader.setShouldCache(true);
  4. imageLoader.get("http://img5.duitang.com/uploads/item/201409/14/20140914162144_MBEmX.jpeg", listener);

代码的思路是产生ImageLoader后,再初始化一个监听器,监听器中传入imageview对象,还有默认的图片,出错时展示的图片,这个很好理解。最后在imageLoader的get方法中传入URL,还有监听器对象即可。

值得注意的是,get方法还有一种变体:

  1. imageLoader.get("http://img5.duitang.com/uploads/item/201409/14/20140914162144_MBEmX.jpeg", listener, 0 ,0);

这里最后传入的数值是得到图片的最大宽、高,其意义和ImageRequest中的宽、高完全一致,可以参考之前的文章。其实,如果你去源码中找找的话,你会发现这两个参数最终都是传给ImageRequest的,所以在此就不做过多讲解了。

2.3 设置缓存

因为我们一上来就修改了源码,所以当我们在执行get()方法前可以通过setShouldCache(false)来取消磁盘缓存,如果你不进行设置的话默认是执行磁盘缓存的。那么如何配置L1缓存呢?刚刚我们的MyImageCache仅仅是一个空实现,现在就开始来完善它。

我的想法是通过LruCache进行图片缓存,分配的缓存空间是5m。如果对LruCache不是很了解,可以看看我之前的文章:详细解读LruCache类

  1. class MyImageCache implements ImageCache {
  2.  
  3. private LruCache<String, Bitmap> mCache;
  4.  
  5. public MyImageCache() {
  6. int maxSize = 5 * 1024 * 1024;
  7. mCache = new LruCache<String, Bitmap>(maxSize) {
  8. @Override
  9. protected int sizeOf(String key, Bitmap bitmap) {
  10. return bitmap.getRowBytes() * bitmap.getHeight();
  11. }
  12. };
  13. }
  14.  
  15. @Override
  16. public Bitmap getBitmap(String url) {
  17. return mCache.get(url);
  18.  
  19. }
  20.  
  21. @Override
  22. public void putBitmap(String url, Bitmap bitmap) {
  23. mCache.put(url, bitmap);
  24. }
  25.  
  26. }

每次执行get方法时,Volley会到MyImageCache中调用getBitmap(),看看有没有内存缓存,如果你返回了null,那么Volley就会从网络上下载,如果不为null,Volley会直接把取得的bitmap展示到imageview中。当图片展示到屏幕上后(无论是这个图片是从内存中读的,还是从磁盘中读的,或者是从网络上下载的),Volley都会自动调用putBitmap,把图片放入内存中缓存起来。

说明:缓存的size是:bitmap.getRowBytes() * bitmap.getHeight(),这里getRowBytes()是返回图片每行的字节数,图片的size应该乘以高度。

注意:imageLoader.setShouldCache(false);仅仅是设置了不实用磁盘缓存,和内存缓存没有任何关系。如果你想要不实用内存缓存,请在自定义的ImageCache中进行处理。

2.4 其他方法

public final boolean shouldCache()

查看是否已经做了磁盘缓存。

void setShouldCache(boolean shouldCache)

设置是否运行磁盘缓存,此方法需要在get方法前使用

public boolean isCached(String requestUrl, int maxWidth, int maxHeight)

判断对象是否已经被缓存,传入url,还有图片的最大宽高

public void setBatchedResponseDelay(int newBatchedResponseDelayMs)

Sets the amount of time to wait after the first response arrives before delivering all responses. Batching can be disabled entirely by passing in 0.

设置第一次响应到达后到分发所有响应之前的整体时间,单位ms,如果你设置的时间是0,那么Batching将不可用。

三、NetworkImageView

NetworkImageView继承自ImageView,你可以认为它是一个可以实现加载网络图片的imageview,十分简单好用。这个控件在被从父控件分离的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题。

3.1 XML

  1. <com.android.volley.toolbox.NetworkImageView
  2. android:id="@+id/network_image_view"
  3. android:layout_width="200dp"
  4. android:layout_height="200dp"
  5. android:layout_gravity="center_horizontal" />

3.2 JAVA

  1.      NetworkImageView networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);
  2. networkImageView.setDefaultImageResId(R.drawable.default_photo);
  3. networkImageView.setErrorImageResId(R.drawable.error_photo);
  4. networkImageView.setImageUrl("http://img5.duitang.com/uploads/item/201409/14/20140914162144_MBEmX.jpeg", imageLoader);

3.3 设置图片的宽高

NetworkImageView没有提供任何设置图片宽高的方法,这是由于它是一个控件,在加载图片的时候它会自动获取自身的宽高,然后对比网络图片的宽度,再决定是否需要对图片进行压缩。也就是说,压缩过程是在内部完全自动化的,并不需要我们关心。NetworkImageView最终会始终呈现给我们一张大小比控件尺寸略大的网络图片,因为它会根据控件宽高来等比缩放原始图片,这点需要注意,如果你想要了解详细原理,请看我之前的ImageRequest介绍。

如果你不想对图片进行压缩的话,只需要在布局文件中把NetworkImageView的layout_width和layout_height都设置成wrap_content就可以了,这样它就会将该图片的原始大小展示出来,不会进行任何压缩。

参考自:

http://blog.csdn.net/guolin_blog/article/details/17482165

详细解读Volley(三)—— ImageLoader & NetworkImageView的更多相关文章

  1. 详细解读Volley(二)—— ImageRequest & Request简介

    上篇文章我们讲到了如何用volley进行简单的网络请求,我们可以很容易的接受到string.JsonObjec类型的返回结果,之前的例子仅仅是一次请求,这里需要说明volley本身就是适合高并发的,所 ...

  2. 详细解读Volley(五)—— 通过源码来分析业务流程

    一.初始化请求队列并运行 我们用Volley时,最先开始的就是初始化请求队列,一种常见的写法如下: public class MyApplication extends Application { p ...

  3. 详细解读Volley(四)—— 自定义Request

    Volley中提供了几个Request,如果我们有特殊的需求,完全可以自定义Request的,自定义Request自然要继承Request,那么本篇就教大家来一步一步地定义一个自己的Request类. ...

  4. 详细解读Volley(一)—— 基本Request对象 & RequestQueue

    Volley它非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕.所以不建议用它去进行下载文件.加载大图的操作.有人可能会问,如 ...

  5. Volley(四)—— ImageLoader & NetworkImageView

    Volley(四)—— ImageLoader & NetworkImageView ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码 ...

  6. volley三种基本请求图片的方式与Lru的基本使用:正常的加载+含有Lru缓存的加载+Volley控件networkImageview的使用

    首先做出全局的请求队列 package com.qg.lizhanqi.myvolleydemo; import android.app.Application; import com.android ...

  7. 相机IMU融合四部曲(三):MSF详细解读与使用

    相机IMU融合四部曲(三):MSF详细解读与使用 极品巧克力 前言 通过前两篇文章,<D-LG-EKF详细解读>和<误差状态四元数详细解读>,已经把相机和IMU融合的理论全部都 ...

  8. volley get post json imagerequest imageloader networkimageview 加载网络本地图片

    官方网站  https://www.androidhive.info/2014/05/android-working-with-volley-library-1/ private void initL ...

  9. Android-Volley网络通信框架(ImageRequest,ImageLoader,NetWorkImageView)

    1.回想 上篇已经学习了,RequestQueue  , StringRequest ,JsonObjectRequest 的使用 2.重点 (1)Volley请求图片的三种方式 (2)ImageRe ...

随机推荐

  1. 【AtCoder】AtCoder Petrozavodsk Contest 001

    A - Two Integers 如果\(X\)是\(Y\)的倍数的话不存在 可以输出\(X \cdot (\frac{Y}{gcd(X,Y)} - 1)\) 代码 #include <bits ...

  2. 018.Zabbix维护时间和模板导入

    一 维护时间 在某些正常业务维护期间,不需要进行告警,可添加维护时间. 二 维护时间添加 2.1 维护 参数 描述 Name 维护名称 Maintenance type 两种维护类型可选: With ...

  3. 002.iSCSI服务端配置

    一 iSCSI target的磁盘种类 大型文件 单一分区(partition) 磁盘 数组 RAID LVM 二 iSCSI创建步骤 建立用于共享的磁盘设备(分区/磁盘/文件) 创建后备磁盘 创建相 ...

  4. 前后端分离之JWT用户认证(转)

    在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了.于是我 ...

  5. 利用angular指令监听ng-repeat渲染完成后执行脚本

    业务中有时需要在异步获取数据并用ng-repeat遍历渲染完页面后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己动手写.有经验的同学都应该知道,在ng-r ...

  6. querySelector/querySelectorAll选择器两个容易忽略的点

    jquery写得多了,原生js大API就容易忘.如果你也是这样,一起来回顾一下HTML5的类jquery选择器querySelector和querySelectorAll吧,querySelector ...

  7. Redis集群主从复制(一主两从)搭建配置教程【Windows环境】

    如何学会在合适的场景使用合适的技术方案,这值得思考. 由于本地环境的使用,所以搭建一个本地的Redis集群,本篇讲解Redis主从复制集群的搭建,使用的平台是Windows,搭建的思路和Linux上基 ...

  8. CAB归档文件提取工具cabextract

    CAB归档文件提取工具cabextract   在对Windows系统进行数字取证中,经常会遇到.cab的文件.该文件是Windows的压缩格式,一般是作为安装包文件.Kali Linux预置了专用的 ...

  9. bzoj 2209 括号序列

    反转操作 + 翻转操作 = 对称操作 因为上面三个操作都是自己的逆操作,所以我们只需要实现对称操作和反转操作,就可以搞定翻转操作. #include <cstdio> #include & ...

  10. JavaScript学习历程和心得体验

    一.前言 在过去,JavaScript只是被用来做一些简单的网页效果,比如表单验证.浮动广告等,所以那时候JavaScript并没有受到重视.自从AJAX开始流行后,人们发现利用JavaScript可 ...