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類。