原文链接:http://blog.csdn.net/singwhatiwanna/article/details/17588159
前言
如果想很好地理解下面的故事,请参看我半年前写的两篇博文:android中图片的三级cache策略(内存、文件、网络) 一 和 android中左右滑屏的实现(广告位banner组件),还有昨天晚上写的android中图片的三级cache策略(内存、文件、网络)之二:内存缓存策略。
文件缓存策略
当一张图片从网络下载成功以后,这个图片会被加入内存缓存和文件缓存,对于文件缓存来说,这张图片将被以url的哈希值加cach后缀名的形式存储在SD卡上,这样,当下一次再需要同一个url的图片的时候,就不需要从网络下载了,而是直接通过url来进行查找。同时一张图片被访问时,它的最后修改时间将被更新,这样的意义在于:当SD卡空间不足的时候,将会按照最后修改时间来删除40%缓存的图片,确切来说,那些修改时间比较早的图片将会被删除。代码展示
- public class ImageFileCache
- {
- private static final String TAG = "ImageFileCache";
- //图片缓存目录
- private static final String IMGCACHDIR = "/sdcard/ImgCach";
- //保存的cache文件宽展名
- private static final String CACHETAIL = ".cach";
- private static final int MB = 1024*1024;
- private static final int CACHE_SIZE = 1;
- //当SD卡剩余空间小于10M的时候会清理缓存
- private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
- public ImageFileCache()
- {
- //清理部分文件缓存
- removeCache(IMGCACHDIR);
- }
- /**
- * 从缓存中获取图片
- */
- public Bitmap getImageFromFile(final String url)
- {
- final String path = IMGCACHDIR + "/" + convertUrlToFileName(url);
- File file = new File(path);
- if (file != null && file.exists())
- {
- Bitmap bmp = BitmapFactory.decodeFile(path);
- if (bmp == null)
- {
- file.delete();
- }
- else
- {
- updateFileTime(path);
- Logger.d(TAG, "get bmp from FileCache,url=" + url);
- return bmp;
- }
- }
- return null;
- }
- /**
- * 将图片存入文件缓存
- */
- public void saveBitmapToFile(Bitmap bm, String url)
- {
- if (bm == null) {
- return;
- }
- //判断sdcard上的空间
- if (FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace())
- {
- //SD空间不足
- return;
- }
- String filename = convertUrlToFileName(url);
- File dirFile = new File(IMGCACHDIR);
- if (!dirFile.exists())
- dirFile.mkdirs();
- File file = new File(IMGCACHDIR +"/" + filename);
- try
- {
- file.createNewFile();
- OutputStream outStream = new FileOutputStream(file);
- bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
- outStream.flush();
- outStream.close();
- }
- catch (FileNotFoundException e)
- {
- Logger.d(TAG, "FileNotFoundException");
- }
- catch (IOException e)
- {
- Logger.d(TAG, "IOException");
- }
- }
- /**
- * 计算存储目录下的文件大小,
- * 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
- * 那么删除40%最近没有被使用的文件
- */
- private boolean removeCache(String dirPath)
- {
- File dir = new File(dirPath);
- File[] files = dir.listFiles();
- if (files == null)
- {
- return true;
- }
- if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
- {
- return false;
- }
- int dirSize = 0;
- for (int i = 0; i < files.length; i++)
- {
- if (files[i].getName().contains(CACHETAIL))
- {
- dirSize += files[i].length();
- }
- }
- if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace())
- {
- int removeFactor = (int) (0.4 * files.length);
- Arrays.sort(files, new FileLastModifSort());
- for (int i = 0; i < removeFactor; i++)
- {
- if (files[i].getName().contains(CACHETAIL))
- {
- files[i].delete();
- }
- }
- }
- if (SdCardFreeSpace() <= CACHE_SIZE)
- {
- return false;
- }
- return true;
- }
- /**
- * 修改文件的最后修改时间
- */
- public void updateFileTime(String path)
- {
- File file = new File(path);
- long newModifiedTime = System.currentTimeMillis();
- file.setLastModified(newModifiedTime);
- }
- /**
- * 计算SD卡上的剩余空间
- */
- private int SdCardFreeSpace()
- {
- StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
- double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
- return (int) sdFreeMB;
- }
- /**
- * 将url转成文件名
- */
- private String convertUrlToFileName(String url)
- {
- return url.hashCode() + CACHETAIL;
- }
- /**
- * 根据文件的最后修改时间进行排序
- */
- private class FileLastModifSort implements Comparator<File>
- {
- public int compare(File file0, File file1)
- {
- if (file0.lastModified() > file1.lastModified())
- {
- return 1;
- }
- else if (file0.lastModified() == file1.lastModified())
- {
- return 0;
- }
- else
- {
- return -1;
- }
- }
- }
- }
说明:上述代码很好理解而且都有注释,不用多说了。