標籤:緩衝策略
1.簡介
Android緩衝原理都是一樣,可以自己封裝。
三級緩衝:
1.記憶體緩衝:緩衝在記憶體中,基於LRU(least recently used )演算法,機器重啟消失。 2.本機快取。緩衝在本地中。一般索引值對形式。(url,filepath) 3.網路緩衝。從網路載入資源,然後緩衝在記憶體、本地中。
2.實現步驟
2.1 記憶體緩衝:
[java] view plain copy
public class MemoryCacheUtils {
private LruCache<String,Bitmap> mMemoryCache;
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手機最大允許記憶體的1/8,即超過指定記憶體,則開始回收
//需要傳入允許的記憶體最大值,虛擬機器預設記憶體16M,真機不一定相同
mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){
//用於計算每個條目的大小
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getByteCount();
return byteCount;
}
};
}
/**
[java] view plain copy
public class LocalCacheUtils {
private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/images";
/**
- 從本地讀取圖片
@param url
*/
public Bitmap getBitmapFromLocal(String url){
String fileName = null;//把圖片的url當做檔案名稱,並進行MD5加密
try {
fileName = MD5Encoder.encode(url); //這裡加不加密無所謂
File file=new File(CACHE_PATH,fileName);
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
- 從網路擷取圖片後,儲存至本機快取
- @param url
@param bitmap
*/
public void setBitmapToLocal(String url,Bitmap bitmap){
try {
String fileName = MD5Encoder.encode(url);//把圖片的url當做檔案名稱,並進行MD5加密 File file=new File(CACHE_PATH,fileName); //通過得到檔案的父檔案,判斷父檔案是否存在 File parentFile = file.getParentFile(); if (!parentFile.exists()){ parentFile.mkdirs(); } //把圖片儲存至本地 bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file)); } catch (Exception e) { e.printStackTrace(); }
}
}
2.3網路緩衝
[java] view plain copy
public class NetCacheUtils {
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) { mLocalCacheUtils = localCacheUtils; mMemoryCacheUtils = memoryCacheUtils; } public NetCacheUtils(){ } /** * 從網路下載圖片 * @param ivPic 顯示圖片的imageview * @param url 下載圖片的網路地址 */ public void getBitmapFromNet(ImageView ivPic, String url) { new BitmapTask().execute(ivPic, url);//啟動AsyncTask } public void getBitmapFromNet(View ivPic, String url) { new BitmapTask_view().execute(ivPic, url);//啟動AsyncTask } public Bitmap getBitmapFromNet(final String url) { //啟動AsyncTask return null; } /** * AsyncTask就是對handler和線程池的封裝 * 第一個泛型:參數類型 * 第二個泛型:更新進度的泛型 * 第三個泛型:onPostExecute的返回結果 */ class BitmapTask extends AsyncTask<Object, Void, Bitmap> { private ImageView ivPic; private String url; /** * 後台耗時操作,存在於子線程中 * @param params * @return */ @Override protected Bitmap doInBackground(Object[] params) { ivPic = (ImageView) params[0]; url = (String) params[1]; return downLoadBitmap(url); } /** * 更新進度,在主線程中 * @param values */ @Override protected void onProgressUpdate(Void[] values) { super.onProgressUpdate(values); } /** * 耗時方法結束後執行該方法,主線程中 * @param result */ @Override protected void onPostExecute(Bitmap result) { if (result != null) { ivPic.setImageBitmap(result); System.out.println("從網路緩衝圖片啦....."); //從網路擷取圖片後,儲存至本機快取 mLocalCacheUtils.setBitmapToLocal(url, result); //儲存至記憶體中 mMemoryCacheUtils.setBitmapToMemory(url, result); } } } /** * AsyncTask就是對handler和線程池的封裝 * 第一個泛型:參數類型 * 第二個泛型:更新進度的泛型 * 第三個泛型:onPostExecute的返回結果 */ @SuppressLint("NewApi") class BitmapTask_view extends AsyncTask<Object, Void, Bitmap> { private View ivPic; private String url; /** * 後台耗時操作,存在於子線程中 * @param params * @return */ @Override protected Bitmap doInBackground(Object[] params) { ivPic = (View) params[0]; url = (String) params[1]; return downLoadBitmap(url); } /** * 更新進度,在主線程中 * @param values */ @Override protected void onProgressUpdate(Void[] values) { super.onProgressUpdate(values); } /** * 耗時方法結束後執行該方法,主線程中 * @param result */ @Override protected void onPostExecute(Bitmap result) { if (result != null) { //ivPic.setImageBitmap(result); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { //Android系統大於等於API16,使用setBackground ivPic.setBackground(new BitmapDrawable(result)); } else { //Android系統小於API16,使用setBackground ivPic.setBackgroundDrawable(new BitmapDrawable(result)); } System.out.println("從網路緩衝圖片啦....."); //從網路擷取圖片後,儲存至本機快取 mLocalCacheUtils.setBitmapToLocal(url, result); //儲存至記憶體中 mMemoryCacheUtils.setBitmapToMemory(url, 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"); int responseCode = conn.getResponseCode(); if (responseCode == 200) { //圖片壓縮 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize=2;//寬高壓縮為原來的1/2 options.inPreferredConfig=Bitmap.Config.ARGB_4444; //Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options); Bitmap bitmap=BitmapFactory.decodeStream(conn.getInputStream()); return bitmap; } } catch (IOException e) { e.printStackTrace(); }catch (Exception e) { } finally { if(conn!=null){ conn.disconnect(); } } return null; }
}
2.4外部寫一個bitmapUtils來調用它們。
[java] view plain copy
public class MyBitmapUtils {
private NetCacheUtils mNetCacheUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
public MyBitmapUtils(){ mMemoryCacheUtils=new MemoryCacheUtils(); mLocalCacheUtils=new LocalCacheUtils(); mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils); } public Bitmap getBitmap(String url){ Bitmap bitmap=null; bitmap=mMemoryCacheUtils.getBitmapFromMemory(url); if(bitmap!=null){ return bitmap; } bitmap = mLocalCacheUtils.getBitmapFromLocal(url); if(bitmap!=null){ mMemoryCacheUtils.setBitmapToMemory(url,bitmap); return bitmap; } return bitmap; } public void disPlay(ImageView ivPic, String url) { Bitmap bitmap; //記憶體緩衝 bitmap=mMemoryCacheUtils.getBitmapFromMemory(url); if (bitmap!=null){ ivPic.setImageBitmap(bitmap); Log.d("iamgecache","從記憶體擷取圖片啦.....--->"+url); return; } //本機快取 bitmap = mLocalCacheUtils.getBitmapFromLocal(url); if(bitmap !=null){ ivPic.setImageBitmap(bitmap); Log.d("iamgecache","從本地擷取圖片啦.....-->"+url); //從本地擷取圖片後,儲存至記憶體中 mMemoryCacheUtils.setBitmapToMemory(url,bitmap); return; } //網路緩衝 mNetCacheUtils.getBitmapFromNet(ivPic,url); Log.d("iamgecache","從網路擷取圖片啦.....-->"+url); } @SuppressLint("NewApi") public void disPlay(View ivPic, String url) { Bitmap bitmap; //記憶體緩衝 bitmap=mMemoryCacheUtils.getBitmapFromMemory(url); if (bitmap!=null){ //ivPic.setImageBitmap(bitmap); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { //Android系統大於等於API16,使用setBackground ivPic.setBackground(new BitmapDrawable(bitmap)); } else { //Android系統小於API16,使用setBackground ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap)); } //ivPic.setBackground(new BitmapDrawable(bitmap)); Log.d("iamgecache","從記憶體擷取圖片啦.....--->"+url); return; } //本機快取 bitmap = mLocalCacheUtils.getBitmapFromLocal(url); if(bitmap !=null){ // ivPic.setImageBitmap(bitmap); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { //Android系統大於等於API16,使用setBackground ivPic.setBackground(new BitmapDrawable(bitmap)); } else { //Android系統小於API16,使用setBackground ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap)); } //ivPic.setBackground(new BitmapDrawable(bitmap)); Log.d("iamgecache","從本地擷取圖片啦.....-->"+url); //從本地擷取圖片後,儲存至記憶體中 mMemoryCacheUtils.setBitmapToMemory(url,bitmap); return; } //網路緩衝 mNetCacheUtils.getBitmapFromNet(ivPic,url); // ivPic.setBackground(new BitmapDrawable(bitmap)); Log.d("iamgecache","從網路擷取圖片啦....-->"+url); }
}
個人封裝的網路緩衝架構的好處是便於修改,自己清楚流程.適合於一些對圖片品質沒那麼高要求而又需要緩衝減少網路訪問的情景.
Android圖片三級緩衝策略