Android网络请求图片缓存本地无OOM支持安卓7.0
在开发中经常遇到异步网络请求图片,为了节约流量经常需要把图片存放在本地文件夹,下次请求直接读取文件夹下面图片。但有可能图片太大造成内存溢出(OOM)。为了解决这些问题专门写了一个类来做这些事情。代码注释十分详细。
1.网络连接采用import java.net.URLConnection;更加快速,更加稳定
2.引入线程池管理
3.图片存放本地,下次访问快速
4.防止OOM【再多再大图片无压力】
5.使用简单方便
6.可直接拖放到工程使用,很稳定
1. 设置图片方法举例:
//高清4K
String url="http://attach.bbs.miui.com/forum/201502/03/150905vpzrbnzksnkbkyhr.jpg";
YnetImg yset=new YnetImg(getApplicationContext());
//路径,imageView,清除错误时候默认加载的图片
yset.set(url, imageView, R.drawable.a);
2. 清除本地缓存:
YnetImg img=new YnetImg(getApplicationContext());
img.clearCache();
- -
3.关键代码
- 关键变量
// 硬引用缓存缓存Bitmap
private static LruCache<String, Bitmap> bitMapLruCache;
// 硬引用缓存存请求队列
private static LruCache<String, String> imageViewCache;
// 记录全部下载任务
downloads = new ArrayList<FileDownloadThread>();
/** 线程队列同时最多运行10个 */
private static ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(10);
- 网络请求,如果缓存有图片直接设置给imageView,缓存没有就本地找,本地没有就网络下载到本地然后设置给imageView,并且记录给缓存
/**
* @Title: set
* @Description: TODO(网络请求,如果缓存有图片直接设置给imageView,缓存没有就本地找,本地没有就网络下载到本地然后设置给imageView,并且记录给缓存)
* @param url
* 下载路径
* @param imageView
* 要设置的imageView
* @param defaultImage
* 出错时显示的defaultImage
* @return void 返回类型
*/
public void set(final String url, final ImageView imageView,
final int defaultImage) {
// 用户传递空值直接拒绝继续执行
if (url == null || imageView == null || defaultImage == 0)
return;
if (bitMapLruCache.get(url) != null) {// 先在缓存中找图片
imageView.setImageBitmap(bitMapLruCache.get(url));// 显示
return;
}
// 判断该imageView是否正在请求该网络,若是则不请求
if (imageViewCache.get(url + imageView.toString()) != null
&& (url + imageView.toString()).equals(imageViewCache.get(url
+ imageView.toString()))) {// 先在缓存中找图片
return;
}
imageViewCache.put(url + imageView.toString(),
url + imageView.toString());
// 给保存文件命名
String fileName = MD5Util.MD5(url) + getLastName(url);
// 开始请求网络
YDownload download = new YDownload(url, path, fileName,
new YDownloadImgListener() {
@Override
public void response(boolean issuccess, String url,
String path, String fileName) {
// 请求回调结果
imageViewCache.remove(url + imageView.toString());// 在请求队列中把删除
// 请求是否成功
if (issuccess) {
// 这样要内存溢出
// Bitmap bitmap =
// BitmapFactory.decodeFile(path+"/"+ fileName);
// 这样可以防止内存溢出
Bitmap bitmap = BitmapFactory.decodeByteArray(
BitmapMemory.decodeBitmap(path + "/"
+ fileName),
0,
BitmapMemory.decodeBitmap(path + "/"
+ fileName).length);
if (bitmap == null) {
Log.e("错误", "读取的文件不能转换成bitmap");
Bitmap bmp = BitmapFactory.decodeResource(
context.getResources(), defaultImage);
imageView.setImageBitmap(bmp);// 显示默认图片
return;
}
bitMapLruCache.put(url, bitmap);// 把bitmap添加保存起来
imageView.setImageBitmap(bitmap);// 显示
} else {
// 把资源文件转换成bitmap
Bitmap bmp = BitmapFactory.decodeResource(
context.getResources(), defaultImage);
imageView.setImageBitmap(bmp);// 显示默认图片
}
}
});
download.setDiskCache(true);// 是否开启缓存
download.setTimeOut(8000);// 设置延迟
download.start();// 开始,将开启一个线程丢入线程队列
}
- 初始化缓存
/**
* 初始化缓存
*/
private void setImageCache() {
if (bitMapLruCache == null) {
int memClass = (((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)))
.getMemoryClass();
int cacheSize = 1024 * 1024 * memClass / 10; // 硬引用缓存容量,为系统可用内存的1/10
bitMapLruCache = new LruCache<String, Bitmap>(cacheSize) {
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap bitmap) {
if (bitmap != null) {// 返回bitmap大小
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {// API
// 19
return bitmap.getAllocationByteCount();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {// API
// 12
return bitmap.getByteCount();
}
return bitmap.getRowBytes() * bitmap.getHeight(); // earlierversion
} else
return 0;
}
};
}
if (imageViewCache == null) {
int memClass = (((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)))
.getMemoryClass();
int cacheSize = 1024 * 1024 * memClass / 10; // 硬引用缓存容量,为系统可用内存的1/10
imageViewCache = new LruCache<String, String>(cacheSize);
}
}
希望大家多多提出意见一起努力进步。
点击这儿下载源代码JAVA类。