Android 開發中對圖片的加載恨常見,爲了防止出現內存溢出,採用三級緩存:
內存緩存,
本地緩存(sd),
網絡緩存。
從網絡下載的圖片保存到內存和sd卡中,之後調用可以直接從內存或者sd卡讀出
/**
* 內存緩存
* @author xiongt
*
*/
public class MemoryCacheUtils {
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory(); // 8;// 模擬器默認是16M
mMemoryCache = new LruCache<String, Bitmap>((int)(maxMemory)){
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getRowBytes()*value.getHeight();//獲取圖片佔用內存大小
return byteCount;
}
};
}
/**
* 從內存讀
* @param url
* @return
*/
public Bitmap getBitmapFromMemory(String url){
return mMemoryCache.get(url);
}
/**
* 寫內存
*/
public void setBitmapToMemory(String url,Bitmap bitmap){
mMemoryCache.put(url, bitmap);
}
}
/** * 本地緩存(sd卡) * @author xiongt * */ public class LocalCacheUtils { public static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/kdumpda_data"; /** * 向SD卡寫圖片 * @param url * @param bitmap */ public void setBitmapToLocal(String url,Bitmap bitmap){ try { // String fileName = MD5Encoder.encode(url); String fileName = url; File file = new File(CACHE_PATH, fileName); File fileParent = file.getParentFile(); if(!fileParent.exists()){// 如果文件夾不存在, 創建文件夾 fileParent.mkdirs(); } //將圖片保存到本地 bitmap.compress(CompressFormat.JPEG, 100,new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } } /** * 從SD卡讀圖片 */ public Bitmap getBitmapFromLocal(String url){ try { String fileName = url; File file = new File(CACHE_PATH, fileName); if(file.exists()){ Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file)); return bitmap; } } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } }
/** * 網絡緩存 * @author xiongt * */ public class NetCacheUtils { private LocalCacheUtils mLocalCacheUtils; private MemoryCacheUtils mMemoryCacheUtils; public NetCacheUtils(LocalCacheUtils mLocalCacheUtils, MemoryCacheUtils mMemoryCacheUtils) { this.mLocalCacheUtils = mLocalCacheUtils; this.mMemoryCacheUtils = mMemoryCacheUtils; } //根據圖片的url去加載圖片 //在本地和內存中緩存 /** * 從網絡下載圖片(異步) * @param ivPic * @param url * @return */ public void getBitmapFromNet(ImageView ivPic,String url){ new BitmapTask().execute(ivPic,url);//啓動AsyncTask,參數在doInBackground中獲取 } /** * 異步任務是 Handler 和線程池的封裝 * 泛型,第一個是參數,第二個是進度更新,第三個是返回結果 * @author xiongt * */ class BitmapTask extends AsyncTask<Object, Void, Bitmap>{ private ImageView ivPic; private String url; /** * 更新進度,主線程 */ @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values);//在doInBackground中調用publishProgress()方法更新 } /** * 後臺耗時方法在此進行,子線程 */ @Override protected Bitmap doInBackground(Object... params) { ivPic = (ImageView) params[0]; url = (String) params[1]; ivPic.setTag(url);// 將url和imageview綁定 return downloadBitmap(url); } /** * 耗時操作完成後,執行該方法,主線程 */ @Override protected void onPostExecute(Bitmap result) { if(result != null){ String bindUrl = (String) ivPic.getTag(); if(url.equals(bindUrl)){// 確保圖片設定給了正確的imageview ivPic.setImageBitmap(result); mLocalCacheUtils.setBitmapToLocal(url, result);// 將圖片保存在本地 mMemoryCacheUtils.setBitmapToMemory(url, result);// 將圖片保存在內存 } } super.onPostExecute(result); } } /** * 下載圖片 * @param url * @return */ public Bitmap downloadBitmap(String url) { HttpURLConnection conn = null; try { conn = (HttpURLConnection) new URL(url).openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.setRequestMethod("GET"); conn.connect(); int responseCode = conn.getResponseCode(); if(responseCode == 200){ InputStream inputStream = conn.getInputStream(); //圖片壓縮處理 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2;//寬高都壓縮爲原來的二分之一, 此參數需要根據圖片要展示的大小來確定 options.inPreferredConfig = Bitmap.Config.ARGB_8888;//設置圖片格式 Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); return bitmap; } } catch (Exception e) { e.printStackTrace(); } finally{ conn.disconnect(); } return null; } }