在Android开发中,我们经常会使用到网络图片资源,而为了避免频繁的访问网络获取图片资源,我们一般会将网络图片缓存到本地或者内存中以方便使用,这就需要使用到图片的三级缓存:
/**
* 继承LruCache实现图片缓存
*
* @author Administrator
*
*/
class BitmapCache extends LruCache {
public BitmapCache(int maxSize) {
super(maxSize);
}
/**
* 返回图片的大小
*/
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}
/**
* 私有构造函数
*/
private ImageCacheUtils(Context context) {
mContext = context;
// 初始化bitmapCache,获得系统可用的最大内存,并将可用内存的1/16作为图片缓存的大小,
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int maxSize = maxMemory / 16;
mBitmapCache = new BitmapCache(maxSize);
}
package com.zk.imagecache;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.v4.util.LruCache;
/**
* 图片三级缓存实现 1、从内存中获得 2、从本地sd卡中获得 3、从网络中获得
*
* @author Administrator
*
*/
public class ImageCacheUtils {
/**
* 上下文
*/
private static Context mContext;
/**
* 单例
*/
private static ImageCacheUtils mImageCacheUtils;
/**
* 缓存bitmap
*/
private static BitmapCache mBitmapCache;
/**
* 私有构造函数
*/
private ImageCacheUtils(Context context) {
mContext = context;
// 初始化bitmapCache,获得系统可用的最大内存,并将可用内存的1/16作为图片缓存的大小,
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int maxSize = maxMemory / 16;
mBitmapCache = new BitmapCache(maxSize);
}
/**
* 获得图片缓存对象
*
* @param context
* @return
*/
public static ImageCacheUtils getInstance(Context context) {
if (mImageCacheUtils == null) {
mImageCacheUtils = new ImageCacheUtils(context);
}
return mImageCacheUtils;
}
/**
* 获得Bitmap对象
*
* @param url
* @return
*/
public Bitmap getBitmap(String url) {
// 将url地址的md5加密后的32位字符作为key,保证唯一性
String key = SecurityUtils.MD5.get32MD5String(url);
// 1、从内存中获得bitmap
Bitmap bitmap = mBitmapCache.get(key);
if (bitmap != null) {
return bitmap;
}
// 2、内存中不存在该bitmap,从sd卡中获取
bitmap = getDiskBitmap(key);
if (bitmap != null) {
return bitmap;
}
// 3、从网络中获得Bitmap
bitmap = getNetBitmap(url);
if (bitmap != null) {
return bitmap;
}
return null;
}
/**
* 将图片保存到内存中
*
* @param url
* @param bitmap
*/
private void saveBitmap(String key, Bitmap bitmap) {
if (mBitmapCache.get(key) == null) {
mBitmapCache.put(key, bitmap);
}
}
/**
* 从sd卡中获得图片
*
* @param key
* @return
*/
private Bitmap getDiskBitmap(String key) {
try {
File file = getDiskFile(key);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
// 加载到内存中
mBitmapCache.put(key, bitmap);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
/**
* 将图片保存到sd卡中
*
* @param key
*/
private void saveDiskBitmap(String key, Bitmap bitmap) {
try {
File file = getDiskFile(key);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(),
bitmap.getHeight(), true);
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获得sd卡存储图片路径
*
* @param url
* @return
*/
private File getDiskFile(String key) {
String path = "";
String externalStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(externalStorageState)) {
path = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
path = mContext.getCacheDir().getAbsolutePath();
}
// 获得图片文件
File dirFile = new File(path + "/imagecache");
if (!dirFile.exists()) {
dirFile.mkdirs();
}
File file = new File(dirFile, key + ".png");
return file;
}
/**
* 从网络中获得图片
*
* @param url
*/
private Bitmap getNetBitmap(String url) {
try {
// 创建一个线程池
ExecutorService pool = Executors.newCachedThreadPool();
Future future = pool.submit(new BitmapCallable(url));
Bitmap bitmap = future.get();
pool.shutdown();
// Bitmap bitmap = new BitmapTask().execute(url).get();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* callable线程
*
* @author Administrator
*
*/
class BitmapCallable implements Callable {
private String path;
public BitmapCallable(String path) {
this.path = path;
}
@Override
public Bitmap call() throws Exception {
HttpClient client = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(path);
HttpResponse response = client.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
InputStream inputStream = response.getEntity().getContent();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap != null) {
String key = SecurityUtils.MD5.get32MD5String(path);
// 保存到内存
saveBitmap(key, bitmap);
// 保存到sd卡
saveDiskBitmap(key, bitmap);
}
inputStream.close();
return bitmap;
}
return null;
}
}
class BitmapTask extends AsyncTask {
@Override
protected Bitmap doInBackground(String... params) {
try {
String path = params[0];
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap != null) {
String key = SecurityUtils.MD5.get32MD5String(path);
// 保存到内存
saveBitmap(key, bitmap);
// 保存到sd卡
saveDiskBitmap(key, bitmap);
}
inputStream.close();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
}
}
/**
* 继承LruCache实现图片缓存
*
* @author Administrator
*
*/
class BitmapCache extends LruCache {
public BitmapCache(int maxSize) {
super(maxSize);
}
/**
* 返回图片的大小
*/
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
}
}
mBtnShow = (Button) findViewById(R.id.btn_show);
mIvShow = (ImageView) findViewById(R.id.iv_show);
mBtnShow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mIvShow.setImageBitmap(ImageCacheUtils
.getInstance(MainActivity.this)
.getBitmap(
"https://img-my.csdn.net/uploads/201407/26/1406383213_3557.jpg"));
}
});