Volley 使用的缓存

在看此文章前建议先阅读一下郭霖大神的blog http://blog.csdn.net/guolin_blog/article/details/17482095一共四篇,仔细看。

下面是我对它里面使用的imageloader 中的cache 进行的一下扩充:

新建一个bitmapcache 类继承自android supportV4提供的LruCache (主要包括硬引用,软引用,以及sdcard本地缓存),代码如下:

public class BitmapCache extends LruCache<String, Bitmap> implements ImageCache {
	private static final int SOFT_CACHE_SIZE = 15; // 软引用缓存容量
	static int maxSize = 10 * 1024 * 1024;
	private static BitmapCache instance = null;//使用单例模式
	private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache; // 软引用缓存

	public static BitmapCache getInstance() {
		if (instance == null) {
			instance = new BitmapCache(maxSize);
			mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(
					SOFT_CACHE_SIZE, 0.75f, true) {
				private static final long serialVersionUID = 6040103833179403725L;

				@Override
				protected boolean removeEldestEntry(
						Entry<String, SoftReference<Bitmap>> eldest) {
					if (size() > SOFT_CACHE_SIZE) {
						return true;
					}
					return false;
				}
			};
		}
		return instance;
	}

	private BitmapCache(int maxSize) {
		super(maxSize);
		initLocalFileManager();
	}

	private void initLocalFileManager() {

	}

	@Override
	protected int sizeOf(String key, Bitmap value) {
		return value.getRowBytes() * value.getHeight();
	}

	@Override
	protected void entryRemoved(boolean evicted, String key, Bitmap oldValue,
			Bitmap newValue) {
		if (oldValue != null)
			// 硬引用缓存容量满的时候,会根据LRU算法把最近没有被使用的图片转入此软引用缓存
			mSoftCache.put(key, new SoftReference<Bitmap>(oldValue));
	}

	@Override
	public Bitmap getBitmap(String url) {
		// 添加本地缓存
		Bitmap tbm = get(url);
		if (tbm == null) {
			// 如果硬引用缓存中找不到,到软引用缓存中找
			synchronized (mSoftCache) {
				SoftReference<Bitmap> bitmapReference = mSoftCache.get(url);
				if (bitmapReference != null) {
					tbm = bitmapReference.get();
					if (tbm != null) {
						// 将图片移回硬缓存
						put(url, tbm);
						mSoftCache.remove(url);
						return tbm;
					} else {
						mSoftCache.remove(url);
					}
				}
			}
		}
		if (tbm == null) {
			tbm = ImageFileCache.getInstance().getBitmap(url);
			if (tbm != null) {
				put(url, tbm);
			}
		}
		return tbm;
	}

	@Override
	public void putBitmap(String url, Bitmap bitmap) {
		put(url, bitmap);
		// 将图片保存在本地
		ImageFileCache.getInstance().saveBitmap(bitmap, url);
	}

	public void clearCache() {
		mSoftCache.clear();
	}
}

上一个类中用到了ImageFileCache,代码如下:

public class ImageFileCache {
	//sdcard 缓存路径
	private static final String CACHDIR = "/image";
	private static final String WHOLESALE_CONV = ".cache";

	private static final int MB = 1024 * 1024;
	private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;

	private static ImageFileCache mInstance;

	private ImageFileCache() {
	}

	public static ImageFileCache getInstance() {
		if (mInstance == null) {
			mInstance = new ImageFileCache();
		}
		return mInstance;
	}

	/**
	 * 从缓存中取出图片
	 *
	 * @param url
	 * @return
	 */
	public synchronized Bitmap getBitmap(final String url) {
		final String path = getDirectory() + "/" + convertUrlToFileName(url);
		File file = new File(path);
		if (file.exists()) {
			Bitmap bmp = BitmapFactory.decodeFile(path);
			if (bmp == null) {
				file.delete();
			} else {
				updateFileTime(path);
				return bmp;
			}
		}
		return null;
	}

	/**
	 * 将图片存入文件缓存
	 *
	 * @param bm
	 *            需要存入的图片
	 * @param url
	 *            图片的url地址
	 */
	public void saveBitmap(Bitmap bm, String url) {
		if (bm == null) {
			return;
		}
		// 判断sdcard上的空间
		if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
			// SD空间不足
			return;
		}
		String filename = convertUrlToFileName(url);

		String dir = getDirectory();
		File dirFile = new File(dir);
		if (!dirFile.exists())
			dirFile.mkdirs();
		File file = new File(dir + "/" + filename);
		try {
			file.createNewFile();
			OutputStream outStream = new FileOutputStream(file);
			bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
			outStream.flush();
			outStream.close();
		} catch (FileNotFoundException e) {
			Log.w("ImageFileCache", "FileNotFoundException");
		} catch (IOException e) {
			Log.w("ImageFileCache", "IOException");
		}
	}

	/**
	 * 修改文件的最后修改时间
	 *
	 * @param path
	 *            文件路径
	 */
	public void updateFileTime(String path) {
		File file = new File(path);
		long newModifiedTime = System.currentTimeMillis();
		file.setLastModified(newModifiedTime);
	}

	/**
	 * 计算SD卡的剩余空间
	 *
	 * @return
	 */
	@SuppressWarnings("deprecation")
	private int freeSpaceOnSd() {
		StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
				.getPath());
		double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat
				.getBlockSize()) / MB;
		return (int) sdFreeMB;
	}

	/**
	 * 将url地址转换成文件名
	 *
	 * @param url
	 * @return
	 */
	private String convertUrlToFileName(String url) {
		String[] strs = url.split("/");
		return strs[strs.length - 1] + WHOLESALE_CONV;
	}

	/**
	 * 获取文件的缓存路径
	 *
	 * @return
	 */
	public String getDirectory() {
		// String dir = getSDPath() + "/" + CACHDIR;
		String dir = CommonUtils.getExternalCacheDir() + CACHDIR;
		return dir;
	}

	/**
	 * 获取SDCard的路径
	 *
	 * @return
	 */
	@SuppressWarnings("unused")
	private String getSDPath() {
		File sdDir = null;
		boolean sdCardExist = Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
		if (sdCardExist) {
			sdDir = Environment.getExternalStorageDirectory(); // 获取根目录
		}
		if (sdDir != null) {
			return sdDir.toString();
		} else {
			return "";
		}
	}

}

这样volley使用的缓存就建好了。

volley 图片加载提供了三种方法,分别是imageRequest 、imageLoader、NetworkImageView.

第三种NetworkImageView使用比较简单,步骤如下:(一般在adapter的getview 中使用)

1. 创建一个RequestQueue对象。

RequestQueue mQueue = Volley.newRequestQueue(context);  

2. 创建一个ImageLoader对象。

mImageLoader = new ImageLoader(mQueue, BitmapCache.getInstance());

3. 在布局文件中添加一个NetworkImageView控件。

4. 在代码中获取该控件的实例。

5. 设置要加载的图片地址。

img.setDefaultImageResId(R.drawable.item_default_img);//img就是上一步获取的NetWorkImageView控件
			img.setErrorImageResId(R.drawable.item_default_img_err);
			img.setImageUrl(getItem(position).getImgFile(), mImageLoader);
时间: 2024-11-08 19:53:03

Volley 使用的缓存的相关文章

请注意,Volley已默认使用磁盘缓存

之前学习volley框架,用ImageLoader可以设置内存缓存,用一个LruCache,就可以避免OOM且图片读取速度快,爽极了. 后来想,如果只是内存缓存的话,那退出程序或者内存不够大了,缓存的图片不就被清理掉了,这样每次启动程序就又得去网上下载图片,流量好贵的. 于是找到了磁盘缓存框架DiskLruCache,这是一个挺著名的开源框架,网易云阅读等APP之前都用它来缓存图片,关于这个框架的使用可以看这篇博客. 找到这个框架后我就着手把DiskLruCache和Volley结合起来,用Lr

Android volley 解析(四)之缓存篇

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

从源码带看Volley的缓存机制

转载请注明出处:http://blog.csdn.net/asdzheng/article/details/45955653 磁盘缓存DiskBasedCache 如果你还不知道volley有磁盘缓存的话,请看一下我的另一篇博客请注意,Volley已默认使用磁盘缓存 DiskBasedCache内部结构 它由两部分组成,一部分是头部,一部分是内容:先得从它的内部静态类CacheHeader(缓存的头部信息)讲起,先看它的内部结构: responseHeaders; } //可以看到,头部类里包含

Android Volley 获取磁盘已有缓存数据

经过学习,我们知道Volley的架构如下: 从架构上我们可以看到,volley有设置缓存机制,当找不到数据缓存或数据缓存过期时,才会联网获取新的数据.Volley 本身有缓存机制,不仅仅默认缓存图片,也有缓存Json数据.通过手机文件管理软件,我们发现Volley缓存地址:/data/data/软件包/cache/volley 目录下. 那么,在联网获取了数据缓存后,如何获取到Volley缓存中的数据呢?在百度上找了一整天的资料都没有说明如何获取到最新的数据.最后还是再stack overflo

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

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

Part1:Volley磁盘缓存

CacheDispatcher CacheEntry和DiskBasedCacheCacheHeader DiskBasedCacheCountingInputStream 缓存的核心DiskBasedCache 初始化逻辑initialize函数 pruneIfNeeded get和put else 思考 LRU算法一定合理吗如何增大缓存的命中率 文件名重复问题 首先研究一下Volley的磁盘缓存原理,它主要包括以下几个类 CacheDispatcher缓存的具体执行类,继承Thread Di

[Android]Volley在没有网络时读取图片缓存时出现的问题

Volley框架实现了L2缓存,却没有实现L1缓存. 我们团队遇到的问题是 当imgurl为类似于"http://www.XXX,com/XXXX/XXXX.png"时能完成加载 当imgurl为"http://192.168.XXX.XXX:8080/XXX/XXX.png"时总是加载错误 经过一周的排查发现 只要在 服务器的Response头中加入'cache-control:public, max-age=43200'(只是示例) -----------原理-

Volley HTTP 缓存机制

Volley HTTP 缓存规则 在介绍Volley的HTTP缓存机制之前,我们首先来看一下HTTP HEADER中和缓存有关的字段有: 规则 字段 示例值 类型 作用 新鲜度 Expires Sat, 23 Jul 2016 03:34:17 GMT 响应 告诉客户端在过期时间之前可以使用副本 Cache-Control no-cache 响应 告诉客户端忽略资源的缓存副本,强制每次请求都访问服务器 no-store 响应 强制缓存在任何情况下都不要保留任何副本 must-revalidate

Android4种网络连接方式HttpClient、HttpURLConnection、OKHttp和Volley优缺点和性能对比

比较的指标: 1.cpu 2.流量 3.电量 4.内存占用 5.联网时间 功能点: 1.重试机制 2.提供的扩展功能 3.易用性 4.是否https 5.是否支持reflect api,OkHttp有配套方法 6.缓存.重试 7.cookie支持session  id会话支持 8.弱网性能和稳定性 9.超时时间,几种超时时间   连接超时,响应超时 10.适配各种机型.4.4和之前版本  2.3  4.1 5.0 4种网络连接方式提供的功能对比表格: 缓存 重试 Https/Http 稳定性 C