给大家介绍一个自己整理的图片下载缓存的工具类。
整体思路:
一,首先使用异步任务去下载图片,下载完成(可在本地保存),调用LruCache的put 方法将图片加入内存缓存中。
二,当第二次查看图片时,先通过调用LruCache,get(key),获取内存缓存中的图片,如果没有,再去查看本地图片是否存在,如果存在,加入内存缓存,如果不存在,就去下载,下载完成加入内存缓存,并保存本地。这样就形成了一个闭环。
在上代码之前先说下LruCache使用步骤:
(1)要设置缓存图片的内存大小
手机内存的获取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory());
(2)LruCache里面的键值对分别是URL和对应的图片
(3)重写sizeOf方法,返回图片数量。
private final static int maxMemory = (int) Runtime.getRuntime().maxMemory();// 获取当前应用程序所分配的最大内存
private final static int cacheSize = maxMemory / 5;// 只分5分之一用来做图片缓存
private static LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(
cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
};
};
//===================下面为具体代码实现=========
具体分三个工具类,代码注释比较详细,就不在多说、、
/**
*第一步通过url判断内存中是否有此图片,然后执行相应的操作
*/
public class BitmapCache {
private final static int maxMemory = (int) Runtime.getRuntime().maxMemory();// 获取当前应用程序所分配的最大内存
private final static int cacheSize = maxMemory / 5;// 只分5分之一用来做图片缓存
//缓存处理类
private static LruCache<String, Bitmap> mLruCache = new LruCache<String, Bitmap>(
cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight() / 1024;
};
};
/**
* @param urlStr所需要加载的图片的url,以String形式传进来,可以把这个url作为缓存图片的key
* @param image ImageView 控件
*/
public static void loadBitmap(String urlStr, ImageView image){
AsyncImageLoader asyncLoader = new AsyncImageLoader(image,
mLruCache);
Bitmap bitmap = asyncLoader.getBitmapFromMemoryCache(urlStr);// 首先从内存缓存中获取图片
if (bitmap != null) {// 如果缓存中存在这张图片则直接设置给ImageView
image.setImageBitmap(bitmap);
}
else {// 否则先设置成默认的图片, 然后执行异步任务AsycnTask 下载图片
image.setImageResource(R.drawable.pic_default_image);
asyncLoader.execute(urlStr);
}
}
}
//==============下载图片异步任务类=========
/**
* 异步任务类,区下载图片,在内存中缓存。
*/
public class AsyncImageLoader extends AsyncTask<String, Void, Bitmap>{
private ImageView image;
private LruCache<String, Bitmap> lruCache;
public AsyncImageLoader(ImageView image, LruCache<String, Bitmap> lruCache) {
super();
this.image = image;
this.lruCache = lruCache;
}
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
//通过url下载图片
bitmap = LoadImageUtil.getBitmap(params[0]);
if(bitmap==null){//图片加载失败,可能url不正确等等
return null;
}else{ //添加内部缓存
addBitmapToMemoryCache(params[0], bitmap);
return bitmap;
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null){
image.setImageBitmap(bitmap);
}
}
//调用LruCache的put 方法将图片加入内存缓存中
private void addBitmapToMemoryCache(String key, Bitmap bitmap){
if (getBitmapFromMemoryCache(key) == null) {
lruCache.put(key, bitmap);
}
}
//调用Lrucache的get 方法从内存缓存中去图片
public Bitmap getBitmapFromMemoryCache(String key) {
return lruCache.get(key);
}
}
//=============具体下载图片类工具===========
public classLoadImageUtil{
/**
* 通过url获取Bitmap
*
* @param 该图片的网络路径
*/
public static Bitmap getBitmap(String urlPath) {
Bitmap bitmap = null;
String fullName = getImageFullName(urlPath);// 本地保存图片的文件名
Log.i(TAG, "fullName" + fullName);
if (judgeExists(fullName)) {
bitmap = BitmapFactory.decodeFile(fullName);
} else {
bitmap = downloadAndSaveBitmap(urlPath, fullName); // 下载保存图片
}
return bitmap;
}
/**
* 判断文件是否存在
*
* @param 文件在本地的完整名
* @return
*/
private static boolean judgeExists(String fullName) {
File file = new File(fullName);
return file.exists();
}
/**
* 拼接一个完整的本地文件名
*
* @param 文件的网络路径
* @return
*/
private static String getImageFullName(String name) {
return FileUtil.PATH_IMAGE+File.separator+ getLastName(name);
}
/**
* 获取最后的‘/’后的文件名,在当地保存
*
* @param name
* @return
*/
private static String getLastName(String name) {
int lastIndexOf = 0;
lastIndexOf = name.lastIndexOf('/');
String sub=name.substring(lastIndexOf, name.length());
return sub;
}
/**
* 下载保存图片
*
* @param urlPath
* 下载路径
* @param fullName
* 文件保存路径+文件名
* @return
*/
private static Bitmap downloadAndSaveBitmap(String urlPath, String fullName) {
Bitmap bitmap = downloadImage(urlPath); // 下载图片
/* 首先判断是否挂载了sdcard */
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
if (sdCardExist) {
if (bitmap != null) {
saveBitmap(fullName, bitmap);
}
} else {
Log.e(TAG, "没有sdcard无法保存图片");
}
return bitmap;
}
/**
* 保存图片
*
* @param fullName图片本地保存的文件夹名
* @param bitmap图片
*/
private static void saveBitmap(String fullName, Bitmap bitmap) {
if (bitmap != null) {
try {
File file = new File(fullName);//文件夹
if (!file.exists()) {
creatFolder(fullName);
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
} else {
}
}
/**
* 创建保存文件的文件夹
*
* @param fullName
* 带文件名的文件路径
* @return
*/
private static void creatFolder(String fullName) {
if (getLastName(fullName).contains(".")) {
String newFilePath = fullName.substring(0,
fullName.lastIndexOf('/'));
File file = new File(newFilePath);
file.mkdirs();
}
}
/**
* 下载图片
*
* @param urlPath
* @return
*/
public static Bitmap downloadImage(String urlPath) {
try {
byte[] byteData = getImageByte(urlPath);
if (byteData == null) {
Log.e(TAG, "没有得到图片的byte,问题可能是path:" + urlPath);
return null;
}
int len = byteData.length;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
if (len > 200000) {// 大于200K的进行压缩处理
options.inSampleSize = 2;
}
return BitmapFactory.decodeByteArray(byteData, 0, len);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "图片下载失败,异常信息是:" + e.toString());
return null;
}
}
/**
* 获取图片的byte数组
*
* @param urlPath
* @return
*/
private static byte[] getImageByte(String urlPath) {
InputStream in = null;
byte[] result = null;
try {
URL url = new URL(urlPath);
HttpURLConnection httpURLconnection = (HttpURLConnection) url
.openConnection();
httpURLconnection.setDoInput(true);
httpURLconnection.connect();
if (httpURLconnection.getResponseCode() == 200) {
in = httpURLconnection.getInputStream();
result = readInputStream(in);
in.close();
} else {
Log.e(TAG, "下载图片失败,状态码是:" + httpURLconnection.getResponseCode());
}
} catch (Exception e) {
Log.e(TAG, "下载图片失败,原因是:" + e.toString());
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* 将输入流转为byte数组
*
* @param in
* @return
* @throws Exception
*/
private static byte[] readInputStream(InputStream in) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = in.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
baos.close();
in.close();
return baos.toByteArray();
}
}