三級緩存詳解

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;
	}




}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章