* 自定义三级缓存工具类
*/
public class MyBitmapUtils {
private NetCacheUtils mNetCacheUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
public MyBitmapUtils() {
mMemoryCacheUtils = new MemoryCacheUtils();
mLocalCacheUtils = new LocalCacheUtils();
mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
}
//加载图片进行展示
public void display(ImageView imageView, String url) {
//内存缓存: 速度很快, 不浪费流量, 优先
Bitmap bitmap = mMemoryCacheUtils.getMemroyCache(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
System.out.println("从内存加载缓存啦!!!");
return;
}
//本地缓存: 速度快, 不浪费流量, 其次
bitmap = mLocalCacheUtils.getLocalCache(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
System.out.println("从本地加载缓存啦!!!");
//写内存缓存
mMemoryCacheUtils.setMemoryCache(url, bitmap);
return;
}
//网络缓存: 速度慢, 浪费流量, 最后
mNetCacheUtils.getBitmapFromNet(imageView, url);
}
}
/**
* 内存缓存
*
* 因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。
*/
public class MemoryCacheUtils {
//private static HashMap<String,Bitmap> mHashMap = new HashMap<String,Bitmap>();
//private HashMap<String, SoftReference<Bitmap>> mHashMap = new HashMap<String, SoftReference<Bitmap>>();
private LruCache<String, Bitmap> mLruCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory();//获取虚拟机分配的最大内存,默认16MB
System.out.println("maxMemory:" + maxMemory);
//LRU: least recentlly used 最近最少使用算法
//A
//B
//C(最近最少使用)
//B
//A
//D
//maxSize:内存缓存上限
mLruCache = new LruCache<String, Bitmap>((int) (maxMemory / 8)) {
//返回单个对象占用内存的大小
@Override
protected int sizeOf(String key, Bitmap value) {
//int byteCount = value.getByteCount();
// return getRowBytes() * getHeight();
//计算图片占用内存大小
int byteCount = value.getRowBytes() * value.getHeight();
return byteCount;
}
};
}
//写缓存
public void setMemoryCache(String url, Bitmap bitmap) {
// SoftReference<Bitmap> soft = new SoftReference<Bitmap>(bitmap);//用软引用包装bitmap
// mHashMap.put(url, soft);
mLruCache.put(url, bitmap);
}
//读缓存
public Bitmap getMemroyCache(String url) {
// SoftReference<Bitmap> soft = mHashMap.get(url);
// if (soft != null) {
// Bitmap bitmap = soft.get();//从软引用中取出当前对象
// return bitmap;
// }
//
// return null;
//return mHashMap.get(url);
return mLruCache.get(url);
}
}
/**
* 本地缓存
*/
public class LocalCacheUtils {
String PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/zhbj_cache/";//缓存文件夹
//写缓存
public void setLocalCache(String url, Bitmap bitmap) {
//将图片保存在本地文件
File dir = new File(PATH);
if (!dir.exists() || !dir.isDirectory()) {
dir.mkdirs();//创建文件夹
}
try {
File cacheFile = new File(dir, MD5Encoder.encode(url));//创建本地文件, 以url的md5命名
//将图片压缩保存在本地; 参1:图片格式, 参2:压缩比(0-100),100表示不压缩; 参3:输出流
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(
cacheFile));
} catch (Exception e) {
e.printStackTrace();
}
}
//读缓存
public Bitmap getLocalCache(String url) {
try {
File cacheFile = new File(PATH, MD5Encoder.encode(url));
if (cacheFile.exists()) {
//缓存存在
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
cacheFile));
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
/**
* 网络缓存
*/
public class NetCacheUtils {
private LocalCacheUtils localCacheUtils;
private MemoryCacheUtils memoryCacheUtils;
public NetCacheUtils(LocalCacheUtils localCacheUtils,
MemoryCacheUtils memoryCacheUtils) {
this.localCacheUtils = localCacheUtils;
this.memoryCacheUtils = memoryCacheUtils;
}
public void getBitmapFromNet(ImageView imageView, String url) {
//异步下载图片
new BitmapTask().execute(imageView, url);
}
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
private ImageView imageView;
private String url;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Bitmap doInBackground(Object... params) {
imageView = (ImageView) params[0];
url = (String) params[1];
imageView.setTag(url);//给当前ImageView打标签
//使用url下载图片
Bitmap bitmap = download(url);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
//给ImageView设置图片
//由于ListView的重用机制,导致某个item有可能展示它所重用的那个item的图片, 导致图片错乱
//解决方案:确保当前设置的图片和当前显示的imageview完全匹配
String url = (String) imageView.getTag();//获取和当前ImageView绑定个url
if (this.url.equals(url)) {//判断当前下载的图片的url是否和imageView的url一致, 如果一致,说明图片正确
imageView.setImageBitmap(result);
System.out.println("从网络下载图片啦!!!");
//写本地缓存
localCacheUtils.setLocalCache(url, result);
//写内存缓存
memoryCacheUtils.setMemoryCache(url, result);
}
}
}
}
//使用url下载图片
public Bitmap download(String url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(6000);
conn.setReadTimeout(6000);
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
InputStream in = conn.getInputStream();
//使用输入流生成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(in);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
return null;
}
}