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);




你可能感兴趣的:(cache,图片,缓存,Volley)