上一篇对Volley做了一个初步的介绍,除了ImaggeRequest稍微有点绕之外,其它的功能跟xuils基本大同小异。再强调ImaggeRequest中的宽高参数maxWidth,maxHeight
在不是[0,0]时候会对图片做缩放。尤其是加载大图片的时候,这个工具很好用。
本篇在此基础上再介绍几个工具。其中会加入缓存的方式,以及最常用的Lruchche方式。
/** * NetworkImageView的使用 */ private void initNetworkImageView() { mNiv.setDefaultImageResId(R.drawable.ic_launcher);//设置默认图片 mNiv.setErrorImageResId(R.drawable.tomcat);//设置错误的图片 String url = "http://192.168.1.100:8080/meinv.jpg"; RequestQueue queue = Volley.newRequestQueue(this); ImageCache imageCache = null; ImageLoader imageLoader= new ImageLoader(queue, imageCache); mNiv.setImageUrl(url, imageLoader); }通过setImageUrl方法,传入一个urll和一个ImageLoader,即可完成url地址的图片加载。其中 ImageLoader接收两个参数:1、请求队列,跟上一篇那些请求队列一样,2:自定义缓存。
首先,点击进入源码:
public interface ImageCache { public Bitmap getBitmap(String url);//获取图片 public void putBitmap(String url, Bitmap bitmap);//存图片 }它是一个接口,因此我们肯定传入一个接口的实现类对象。而且这个接口没有任何的实现类,从而想到,volley并没有给我们提供缓存,仅仅使我们一个规范:它是必须需要我们自己去实现该接口,也就是自定义缓存。
先看看什么是内存缓存:
存储结构/容器/集合
?Map<String,Bitmap>删除策略/算法
,我们定义的存储结构
,不能继续缓存图片的时候.需要进行清理
删除策略
的使用场景
1、LRU:加载电影海报图。假设到四月份的时候,内存的海报图已经满了,那么五月份的时候海报就无法存入内存。那么就要把图片缓存在内存中去掉。我们看到:即使一月份卖的好,在四月份并没有多少人去看。最近使用最少,我就删除一月份。这就是LRU策略。
2、删除使用次数最少:下面这种情况,显然再加入图片放不进去,会报OOM。这时候这个策略就派上用场,假设右下角仅仅使用过一次,其他的都使用了上百次。那么我就有限删除右下角哪张图片,再去缓存新的图片。这就是删除使用次数最少
3、删除占用体积最大:内存已满,哪个5M的占用空间最大,我如果想加入新的图片,就把最大那张图片删掉。这就是删除占用体积最大。
再回到Lrucache:
一个工具方法,提供了基于
Lru缓存策略
的强引用
的内存缓存,存储结构使用的LinkedHashmap
LinkedHashmap使用
LruCache在什么地方可以找到?
public class LruCache<K, V> { private final LinkedHashMap<K, V> map;跟踪map对象,看他是如何实例化的:
this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
这三个参数,上边已经总结过了:重点要看第三个参数,再用一张图片描述一下:(设置为true后)
初始化LruCache:
定义cache大小
初始化这个cache前需要设定这个cache的大小,这里的大小官方推荐是用当前app可用内存的八分之一,当然你可以视情况而定。我这里定义大小为5*1024*1024 byte大小
/* 内存缓存 */ private LruCache<String, Bitmap> mMemoryCache;设定缓存时要设定泛型,针对的是hashMap,你可以当作是key-value。我这里缓存的是bitmap,用到的key是string对象。
LruCache<String, Bitmap> lruCache; //构造放方法,初始化 public MyImageCache(){ int memoryCacheSize = 5*1024 * 1024 ;//分配内存为多大 //覆写sizeOf方法 lruCache = new LruCache<String, Bitmap>(memoryCacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // 重写此方法来衡量每张图片的大小//这个单位要和size的单位一样都应该是byte return bitmap.getByteCount();//byte单位,与上边一致 } }; // 初始化LruCache对象 }通过缓存的值来初始化了cache对象,然后重写了sizeOf()方法。
添加/删除缓存
当我们初始化缓存后我们就应该能给这个缓存添加对象和移除对象。
@Override public Bitmap getBitmap(String url) {// 取图片 // TODO Auto-generated method stub return lruCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) {// 存图片 // TODO Auto-generated method stub lruCache.put(url, bitmap); }PS:对于Lrucache的案例,会在安卓简易实战教程里面给出案例。
然后再回到开始介绍的NetworkImageView代码位置,把这个自定义缓存对象传入:
/** * NetworkImageView的使用 */ private void initNetworkImageView() { findViewById(R.id.btn4).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mNiv.setDefaultImageResId(R.drawable.ic_launcher);//设置默认图片 mNiv.setErrorImageResId(R.drawable.tomcat);//设置错误的图片 String url = "http://192.168.1.100:8080/meinv.jpg"; RequestQueue queue = Volley.newRequestQueue(MainActivity.this); ImageCache imageCache = new MyImageCache(); ImageLoader imageLoader= new ImageLoader(queue, imageCache); mNiv.setImageUrl(url, imageLoader); } }); }
紧跟脚步,就是NetworkImageView的使用,因为已经介绍完了larucache,这里就特别的简单了。直接上代码就好了。如下:
/** * imageloader的使用 */ private void initImageLoader() { findViewById(R.id.btn5).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { RequestQueue queue = Volley.newRequestQueue(MainActivity.this); ImageCache imageCache = new MyImageCache(); ImageLoader imageLoader = new ImageLoader(queue, imageCache); String requestUrl = "http://192.168.1.100:8080/meinv.jpg"; imageLoader.get(requestUrl, new ImageListener() { @Override public void onErrorResponse(VolleyError error) { System.out.println("error:"+error.getMessage()); } @Override public void onResponse(ImageContainer response, boolean isImmediate) { Bitmap bitmap = response.getBitmap(); iv.setImageBitmap(bitmap); } },200,100);//表示有缩放。0,0无缩放 } }); }