在看此文章前建议先阅读一下郭霖大神的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(); } }
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);