android多级图片缓存
来源:互联网 发布:免费手机相册制作软件 编辑:程序博客网 时间:2024/04/28 17:36
当要加载网络图片时使用缓存能提高性能又能减少服务器的压力。为了兼顾速度与缓存图片的数量应使用多级缓存
1传入url从LinkedHashMap获取图片,LinkedHashMap可以采用LRU算法按顺序插入元素,这样LinkedHashMap可以只保存最近使用的N个元素。
2如果hashmap没有此图片则从 ConcurrentHashMap<String, SoftReference<Bitmap>>获取图片。这里使用了SoftReference(软引用) 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。软引用与LinkedHashMap配合使用,当LinkedHashMap插入元素时,如果LinkedHashMap的元素数目大于某个值,则把这个元素插入 ConcurrentHashMap<String, SoftReference<Bitmap>>中,而不是插入LinkedHashMap中。这样保证了速度又使得缓存图片的数量尽量的大。
3如果 ConcurrentHashMap<String, SoftReference<Bitmap>>没有找到这个图片,则从sd卡中寻找,找到则插入到LinkedHashMap中。
4如果sd卡中没有图片,则从网络中下载图片,并把图片保存在sd卡以及插入到LinkedHashMap中。
public class CacheBitmap {
//图片所在的文件夹private final String imgDir=Tool.getSDPath()+File.separator+"weixun"+File.separator+"img";
//本地最多缓存200张图片
private final int maxImgCount=200;
//sdcard的剩余容量至少为minSDCacheSize
private final int minSDCacheSize=2;
//内存缓存的图片数量
private final int cacheSize=20;
private final int mb=1024*1024;
private static CacheBitmap instance;
private static final String TAG="common.CacheBitmap";
private CacheBitmap()
{
}
public static CacheBitmap getInstance()
{
if(instance==null)
{
instance=new CacheBitmap();
}
return instance;
}
/*
*返回图片文件
*
*@param url 图片url地址
*@return
*/
public Bitmap getBitmap(String url)
{
if (url.equals(""))
{
return null;
}
else
{
Bitmap bmp=null;
String imgName=Tool.MD5(url);
//从缓存中获取位图
bmp=getCacheBitmap(imgName);
if(bmp==null)
{
//Log.v(TAG, "getCacheBitmap(imgName) is return null");
bmp=getLocalBitmap(imgName);
if(bmp==null)
{
//Log.v(TAG, "getLocalBitmap(imgName) is return null");
bmp=getWebBitmap(url,imgName);
}
}
if(bmp!=null)
{
//更新文件最近被使用时间
updateFileTime(imgName);
}
return bmp;
}
}
/**
* 从缓存中获取图片
*/
private Bitmap getCacheBitmap(String imgName)
{
// 先从mHardBitmapCache缓存中获取
synchronized (bitmapCache)
{
final Bitmap bitmap =bitmapCache.get(imgName);
if (bitmap != null)
{
//如果找到的话,把元素移到linkedhashmap的最前面,从而保证在LRU算法中是最后被删除
// bitmapCache.remove(imgName);
//bitmapCache.put(imgName,bitmap);
return bitmap;
}
}
//如果mHardBitmapCache中找不到,到mSoftBitmapCache中找
SoftReference<Bitmap> bitmapReference = softBitmapCache.get(imgName);
if (bitmapReference != null)
{
final Bitmap bitmap =bitmapReference.get();
if (bitmap != null)
{
bitmapCache.put(imgName, bitmap);
return bitmap;
}
else
{
softBitmapCache.remove(imgName);
}
}
return null;
}
/*
* 本地获取图片信息
* @param url 图片路径
* @return bitmap对象
*/
private Bitmap getLocalBitmap(String imgName)
{
String path =imgDir+ File.separator + imgName;
File f = new File(path);
// 当图片文件在sd卡中存在时,从sd卡中获取位图
if (f.exists()&&f.isFile())
{
Bitmap bitmap =decodeFile(imgDir+ File.separator + imgName);
if(bitmap!=null)
{
bitmapCache.put(imgName,bitmap);
}
return bitmap;
}
return null;
}
/*
* 抓取远程图片
* @param imgUrl 图片地址
* @return
*/
private Bitmap getWebBitmap(String imgUrl,String imgName)
{
Bitmap bitmap=Tool.getWebBitmap(imgUrl);
if(bitmap!=null)
{
//将位图放入缓存
bitmapCache.put(imgName,bitmap);
try
{
//如果sd卡中图片数量过多,则用LRU算法清除一些图片
removeCache();
//将文件保存在sd卡
saveInSDCard(bitmap,imgName);
}
catch(Exception e)
{
e.printStackTrace();
}
}
return bitmap;
}
private Bitmap decodeFile(String path)
{
BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false;
bfOptions.inPurgeable=true;
bfOptions.inInputShareable=true;
bfOptions.inTempStorage=new byte[ConfigBLL.ImageMaxWidth * ConfigBLL.ImageMaxHeight];
File file=new File(path);
FileInputStream fs=null;
try
{
fs = new FileInputStream(file);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
Bitmap bm=null;
try
{
if(fs!=null) bm=BitmapFactory.decodeFileDescriptor(fs.getFD(), null, bfOptions);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(fs!=null)
{
try
{
fs.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return bm;
}
/*
* 把位图保持在sdcard
* @param bmp 要保存的位图
* @param imgName图片的名字
*/
private void saveInSDCard(Bitmap bmp,String imgName)
{
File f=new File(imgDir);
if(!f.exists())
{
f.mkdirs();
}
File imgFile=new File(f,imgName);
try
{
imgFile.createNewFile();
FileOutputStream fos=new FileOutputStream(imgFile);
bmp.compress(CompressFormat.JPEG, 70, fos);
fos.flush();
fos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* 修改文件的最后修改时间
* @param fileName
*/
private void updateFileTime(String imgName)
{
File file = new File(imgDir,imgName);
long newModifiedTime =System.currentTimeMillis();
file.setLastModified(newModifiedTime);
}
/**
*计算存储目录下的文件大小,如果图片的容量超标或者sd容量不足minSDCacheSiz则
*删除40%最近没有被使用的文件
*/
private void removeCache()
{
File f = new File(imgDir);
File[] files = f.listFiles();
//这样使得每下载20张图片才会检查是否要清除多余的图片
if (files == null)
{
return;
}
/*int dirSize = 0;
for (int i = 0; i < files.length;i++)
{
dirSize += files[i].length();
} */
if (files.length> maxImgCount||minSDCacheSize > getSdcardFreeSpace())
{
int removeFactor = (int) ((0.4 *files.length) + 1);
Arrays.sort(files, comparatorFile);
for (int i = 0; i <removeFactor; i++)
{
files[i].delete();
}
}
}
/*
* 获取sdcard上的剩余空间 ,md为单位
* @return
*/
private int getSdcardFreeSpace()
{
StatFs stat = new StatFs(Environment.getExternalStorageDirectory() .getPath());
return (int)(((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / mb);
}
/**
* 根据文件的最后修改时间进行排序
*/
Comparator<File> comparatorFile=new Comparator<File>()
{
public int compare(File arg0, File arg1)
{
if (arg0.lastModified() >arg1.lastModified())
{
return 1;
}
else if (arg0.lastModified() ==arg1.lastModified())
{
return 0;
}
else
{
return -1;
}
}
};
/*
* 图片的缓存容器,当map的size大于20时,把最近不常用的key放到softBitmapCache中,从而保证bitmapCache的效率
*/
private final HashMap<String, Bitmap> bitmapCache = new LinkedHashMap<String, Bitmap>(cacheSize/ 2, 0.75f, true)
{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest)
{
if (size() >cacheSize)
{
//当map的size大于20时,把最近不常用的key放到softBitmapCache中,从而保证bitmapCache的效率
softBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true;
}
else
{
return false;
}
}
};
/**
*当bitmapCache的key大于20的时候,会根据LRU算法把最近没有被使用的key放入到这个缓存中。
*Bitmap使用了SoftReference,当内存空间不足时,此cache中的bitmap会被垃圾回收掉
*/
private final ConcurrentHashMap<String, SoftReference<Bitmap>> softBitmapCache =
new ConcurrentHashMap<String,SoftReference<Bitmap>>(cacheSize / 2);
}
- android多级图片缓存
- Bitmap_多级缓存实现图片加载
- Android缓存:图片缓存管理
- Android图片缓存,三级缓存
- android图片缓存
- Android 远程图片缓存
- Android 图片缓存
- Android图片缓存
- Android图片本地缓存
- android 缓存 图片
- android 图片缓存管理
- Android--SoftReference缓存图片
- Android图片缓存管理
- Android:图片缓存
- Android LruCache 缓存图片
- Android图片缓存
- Android 图片缓存处理
- android图片缓存
- libevent源码深度剖析二
- LeetCode——Word Ladder II
- HTML学习笔记(四)HTML 属性
- 界面框架—可编辑表格
- 测试函数JavaScript单元测试工具使用—QUnit
- android多级图片缓存
- POJ 1149 PIGS (最大流)
- wordpress后台修改“WordPress 地址(URL)”后无法打开的解决方法
- Lovekey+26进制大数相加
- HDU 1212求余
- hdu 1116 Play on Words
- .NET中通过域验证用户名和密码
- HTML学习笔记(五) HTML 标题
- system string to std string