您的位置:首页 > 理论基础 > 计算机网络

android中图片的三级cache策略(内存、文件、网络)之三:文件缓存策略

2015-12-24 21:02 633 查看

前言

如果想很好地理解下面的故事,请参看我半年前写的两篇博文:android中图片的三级cache策略(内存、文件、网络)
一 和 android中左右滑屏的实现(广告位banner组件),还有昨天晚上写的android中图片的三级cache策略(内存、文件、网络)之二:内存缓存策略

文件缓存策略

当一张图片从网络下载成功以后,这个图片会被加入内存缓存和文件缓存,对于文件缓存来说,这张图片将被以url的哈希值加cach后缀名的形式存储在SD卡上,这样,当下一次再需要同一个url的图片的时候,就不需要从网络下载了,而是直接通过url来进行查找。同时一张图片被访问时,它的最后修改时间将被更新,这样的意义在于:当SD卡空间不足的时候,将会按照最后修改时间来删除40%缓存的图片,确切来说,那些修改时间比较早的图片将会被删除。

代码展示

[java] view
plaincopy





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;

}

}

}

}

说明:上述代码很好理解而且都有注释,不用多说了。

到这里,整个banner体系的代码都被介绍了,希望代码中的思想能够对大家有所启发,谢谢大家的捧场!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: