简单实现Android图片三级缓存机制
生活随笔
收集整理的這篇文章主要介紹了
简单实现Android图片三级缓存机制
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
????用戶在使用我們的APP時(shí),通常會(huì)重復(fù)瀏覽一些圖片,這時(shí)如果每一次瀏覽都需要通過網(wǎng)絡(luò)獲取圖片,那么將會(huì)非常流量。為了節(jié)省用戶流量,提高圖片加載效率,我們通常使用圖片三級(jí)緩存策略,即通過網(wǎng)絡(luò)、本地、內(nèi)存三級(jí)緩存圖片,來減少不必要的網(wǎng)絡(luò)交互,避免浪費(fèi)流量。
????網(wǎng)上已經(jīng)有很多講述圖片三級(jí)緩存的策略,這次我也來實(shí)現(xiàn)一次三級(jí)緩存,其中用到了LRU+SoftReference關(guān)于LRU算法,可以參考我之前的博客LinkedHashMap最佳實(shí)踐:LruCache。首先我將整個(gè)機(jī)制流程展示給大家:
下面是源碼實(shí)現(xiàn):
/*** @ClassName: CastielImageLoader * @Description: LRU+SoftReference* @author 猴子搬來的救兵 http://blog.csdn.net/mynameishuangshuai*/ public class CastielImageLoader {private static final int MAX_CAPACITY = 20;// 鏈表長度private static Context mContext;// 獲取APP的緩存地址private static CastielImageLoader castielImageLoader;// 鍵是圖片地址、值是軟引用private static final LinkedHashMap<String, SoftReference<Bitmap>> firstCacheMap = new LinkedHashMap<String, SoftReference<Bitmap>>(MAX_CAPACITY) {protected boolean removeEldestEntry(java.util.Map.Entry<String, java.lang.ref.SoftReference<Bitmap>> eldest) {// 返回true表示移除最老的軟引用,保證內(nèi)存平衡if (this.size() > MAX_CAPACITY) {return true;} else {// 否則往磁盤中添加diskCache(eldest.getKey(), eldest.getValue());return false;}}};/*** 單例模式加載CastielImageLoader* @return*/public static CastielImageLoader getInstance() {if (castielImageLoader == null) {castielImageLoader = new CastielImageLoader();}return castielImageLoader;}/*** 加載圖片到對(duì)應(yīng)組件* * @param key 所需加載的路徑* @param view 被加載的組件* @param drawable 沒有加載前默認(rèn)顯示圖片*/@SuppressWarnings("deprecation")public void loadImage(String key, ImageView view, Drawable drawable ,Context context) {mContext = context;synchronized (view) {// 檢查緩存中是否已有Bitmap bitmap = getFromCache(key);if (bitmap != null) {// 如果有了就從緩存中取出顯示view.setImageBitmap(bitmap);} else {// 軟應(yīng)用緩存中不存在,磁盤中也不存在,只能下載// 下載之前應(yīng)該先放一張默認(rèn)圖,用來友好顯示view.setBackgroundDrawable(drawable);// 用異步任務(wù)去下載new CastielAsyncImageLoaderTask(view).execute(key);}}}/*** 判斷緩存中是否已經(jīng)有了,如果有了就從緩存中取出* * @param key* @return*/private Bitmap getFromCache(String key) {// 檢查內(nèi)存軟引中是否存在synchronized (firstCacheMap) {if (firstCacheMap.get(key) != null) {// 內(nèi)存軟引用中有Bitmap bitmap = firstCacheMap.get(key).get();if (bitmap != null) {// 說明拿到了firstCacheMap.put(key, new SoftReference<Bitmap>(bitmap));return bitmap;}}}// 檢查磁盤中是否存在Bitmap bitmap = getFromLocalSD(key);if (bitmap != null) {// 硬盤中有firstCacheMap.put(key, new SoftReference<Bitmap>(bitmap));return bitmap;}return null;}/*** 判斷本地磁盤中是否已經(jīng)有了該圖片,如果有了就從本地磁盤中取出* @param key* @return*/private Bitmap getFromLocalSD(String key) {String fileName = MD5Util.getMD5Str(key);if (fileName == null) {// 如果文件名為Null,直接返回nullreturn null;} else {String filePath = mContext.getCacheDir().getAbsolutePath() + File.separator + fileName;InputStream is = null;try {is = new FileInputStream(new File(filePath));Bitmap bitmap = BitmapFactory.decodeStream(is);return bitmap;} catch (FileNotFoundException e) {e.printStackTrace();} finally {try {is.close();} catch (IOException e) {e.printStackTrace();}}}return null;}/*** 把圖片緩存到本地磁盤,拿到圖片,寫到SD卡中* * @param key 圖片的URL* @param value Bitmap*/private static void diskCache(String key, SoftReference<Bitmap> value) {// 把寫入SD的圖片名字改為基于MD5加密算法加密后的名字String fileName = MD5Util.getMD5Str(key);String filePath = mContext.getCacheDir().getAbsolutePath() + File.separator + fileName;FileOutputStream os = null;try {os = new FileOutputStream(new File(filePath));if (value.get() != null) {value.get().compress(Bitmap.CompressFormat.JPEG, 60, os);}} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}}}/*** * @ClassName: MyAsyncImageLoaderTask * @Description: 異步加載圖片 * @author */class CastielAsyncImageLoaderTask extends AsyncTask<String, Void, Bitmap>{private ImageView imageView;// 圖片組件private String key;//圖片路徑public CastielAsyncImageLoaderTask(ImageView imageView) {this.imageView = imageView;}@Overrideprotected Bitmap doInBackground(String... params) {this.key = params[0];// 圖片的路徑Bitmap bitmap = castielDownload(key);return bitmap;}@Overrideprotected void onPostExecute(Bitmap result) {super.onPostExecute(result);if (result != null) {// 說明已經(jīng)下載下來了addFirstCache(key,result);imageView.setImageBitmap(result);// 加載網(wǎng)絡(luò)中的圖片}}}/*** 根據(jù)圖片路徑執(zhí)行圖片下載* @param key* @return*/public Bitmap castielDownload(String key) {InputStream is = null;try {is = CastielHttpUtils.castielDownLoad(key);return BitmapFactory.decodeStream(is);// InputStream這種加載方式暫用內(nèi)存最小} catch (IOException e) {e.printStackTrace();} finally {try {is.close();} catch (IOException e) {e.printStackTrace();}}return null;}/*** 添加到緩存中去* @param key* @param result*/public void addFirstCache(String key, Bitmap result) {if (result != null) {synchronized (firstCacheMap) {firstCacheMap.put(key, new SoftReference<Bitmap>(result));}}} }網(wǎng)絡(luò)加載工具類 CastielHttpUtils.java
public class CastielHttpUtils {public static InputStream castielDownLoad(String key) throws IOException{HttpURLConnection conn = (HttpURLConnection) new URL(key).openConnection();return conn.getInputStream();} }測試,調(diào)用我們的圖片緩存工具 MainActivity.java
public class MainActivity extends Activity {ImageView img;String imgURl = "http://img2.imgtn.bdimg.com/it/u=3722998253,3365379445&fm=21&gp=0.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);img = (ImageView) findViewById(R.id.img);CastielImageLoader.getInstance().loadImage(imgURl, img, this.getResources().getDrawable(R.drawable.ic_launcher),MainActivity.this);}}布局文件 activity_main
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><TextView android:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="猴子搬來的救兵 http://blog.csdn.net/mynameishuangshuai" /><ImageView android:id="@+id/img"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/tv"android:layout_marginLeft="20dp"android:layout_marginTop="80dp"android:src="@drawable/tt" /></RelativeLayout>測試加載圖片結(jié)果如下:
總結(jié)
以上是生活随笔為你收集整理的简单实现Android图片三级缓存机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【算法笔记】【几何初步、数学初步、矩阵计
- 下一篇: AEAI Portal V3.5.2门户