Android圖片三級緩存開發(fā)
因為目前工程無法使用第三方,只能搞一個三級緩存了三級緩存分為內(nèi)存緩存,本地緩存,網(wǎng)絡緩存;緩存的步驟依次是網(wǎng)絡,內(nèi)存,本地,然后取的順序為內(nèi)存,本地,網(wǎng)絡。在加載圖片時引用時盡量采用弱引用避免出現(xiàn)圖片過多產(chǎn)生OOM.。
1、內(nèi)存緩存,android為我們提供LruCache=其中維護著一個LinkedHashMap。LruCache可以用來存儲各種類型的數(shù)據(jù),我們設置它的大小,一般是系統(tǒng)最大存儲空間的1/8.
public class MemoryCacheUtil { private LruCache<String, Bitmap> lruCache; public MemoryCacheUtil(){ int maxSize = (int) (Runtime.getRuntime().maxMemory()/8); // 一般獲取當前應用的最大內(nèi)存的1/8作為LruCache的容量 lruCache = new LruCache<String, Bitmap>(maxSize){ // 設置當前添加的圖片的大小 @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes()*value.getHeight(); } }; } // 從內(nèi)存緩存取圖片 public Bitmap getBitmap(String url){ return lruCache.get(url); } // 在內(nèi)存緩存存圖片 public void putBitmap(String url,Bitmap bitmap){ lruCache.put(url, bitmap); } }
2、本地緩存根據(jù)url,獲取本地文件,把url進行md5加密,作為文件名,保證文件的正確性.
MD5加密工具類
public class MD5Encoder { public static String encode(String string) throws Exception { byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) { hex.append("0"); } hex.append(Integer.toHexString(b & 0xFF)); } return hex.toString(); } }
本地緩存
public class LocalCacheUtil { private String CACHE_URl; private MemoryCacheUtil memoryCacheUtil; public LocalCacheUtil(MemoryCacheUtil memoryCacheUtil){ // 初始化本地存儲的路徑 CACHE_URl = Environment.getExternalStorageDirectory().getAbsoluteFile()+ "/test"; this.memoryCacheUtil = memoryCacheUtil; } // 從本地sdcard取圖片 public Bitmap getBitmap(String url){ // 根據(jù)url,獲取本地文件,把url進行md5加密,作為文件名 try { String fileName = MD5Encoder.encode(url); File file = new File(CACHE_URl, fileName); if(file.exists()){// 判斷當前文件是否存在 // 把當前文件轉換成Bitmap對象 Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); // 需往內(nèi)存中存一份 memoryCacheUtil.putBitmap(url, bitmap); return bitmap; } } catch (Exception e) { e.printStackTrace(); } return null; } // 往本地存圖片的方法 public void saveBitmap(String url,Bitmap bitmap){ try { String fileName = MD5Encoder.encode(url); File file = new File(CACHE_URl, fileName); // 判斷是否需要創(chuàng)建父目錄 File parentFile = file.getParentFile(); if(!parentFile.exists()){ parentFile.mkdirs(); } // 把Bitmap對象保存到文件中 質(zhì)量越高壓縮速度越慢 OutputStream stream = new FileOutputStream(file); bitmap.compress(CompressFormat.PNG, 100, stream);//第一個參數(shù)可以設置圖片格式,第二個圖片壓縮質(zhì)量,第三個為圖片輸出流 } catch (Exception e) { e.printStackTrace(); } } }
3、網(wǎng)絡緩存使用異步加載AsyncTask,使用其有二種原因:
1.doInBackground運行在子線程,做網(wǎng)絡請求耗時操作,避免主線程堵塞;
2.onPreExecute和onPostExecute便于更新UI提高用戶體驗。
public class NetCacheUtil { private MemoryCacheUtil memoryCacheUtil; private LocalCacheUtil localCacheUtil; private ListView lv_image_list; public NetCacheUtil(MemoryCacheUtil memoryCacheUtil,LocalCacheUtil localCacheUtil){ this.memoryCacheUtil = memoryCacheUtil; this.localCacheUtil = localCacheUtil; } public void display(ImageView imageView ,String url, ListView lv_image_list){ this.lv_image_list = lv_image_list; new MyAsyncTask(imageView).execute(new Object[]{url,imageView}); } class MyAsyncTask extends AsyncTask<Object, Void, Bitmap>{ private ImageView imageView; private int position; public MyAsyncTask(ImageView imageView2) { position = (Integer) imageView2.getTag(); } // 運行在主線程,做準備操作,在doInBackground之前,可以放置加載條提高用戶體驗 @Override protected void onPreExecute() { super.onPreExecute(); } // 運行在子線程,做耗時操作 @Override protected Bitmap doInBackground(Object... params) { // 獲取url,下載圖片 String url = (String) params[0]; // 獲取ImageView imageView = (ImageView) params[1]; try { // 下載圖片 HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); conn.connect();// 連接網(wǎng)絡 // 獲取響應碼 int resCode = conn.getResponseCode(); if(resCode==200){// 訪問成功 // 把服務器返回的輸入流轉換成Bitmap對象 Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream()); // 保存到本地和內(nèi)存 memoryCacheUtil.putBitmap(url, bitmap); localCacheUtil.saveBitmap(url, bitmap); return bitmap; } } catch (Exception e) { e.printStackTrace(); } return null; } // 運行在主線程,更新界面,在doInBackground之后 @Override protected void onPostExecute(Bitmap result) { // 判斷線程開始時,那個位置是否還在Listview中 ImageView view = (ImageView) lv_image_list.findViewWithTag(position); if(view!=null){ view.setImageBitmap(result); } super.onPostExecute(result); } } }
4、封裝三級緩存形成ImageUtil,因內(nèi)存緩存中取速度較快,所以先從內(nèi)存緩存中取,取不到->本地緩存中取,取不到->網(wǎng)絡緩存中取。
public class ImageUtils { private MemoryCacheUtil memoryCacheUtil; private LocalCacheUtil localCacheUtil; private NetCacheUtil netCacheUtil; public ImageUtils(){ memoryCacheUtil = new MemoryCacheUtil(); localCacheUtil = new LocalCacheUtil(memoryCacheUtil); netCacheUtil = new NetCacheUtil(memoryCacheUtil,localCacheUtil); } public void display(ImageView imageView, String url, ListView lv_photo_list) { Bitmap bitmap = null; /** * 因內(nèi)存緩存中取速度較快 * 內(nèi)存緩存中取,取不到->本地緩存中取,取不到->網(wǎng)絡緩存中取 */ bitmap = memoryCacheUtil.getBitmap(url);//從內(nèi)存緩存取圖片 if(bitmap!=null){ imageView.setImageBitmap(bitmap); return; } bitmap = localCacheUtil.getBitmap(url);//從本地緩存取圖片 if(bitmap!=null){ imageView.setImageBitmap(bitmap); return; } // 開啟線程訪問網(wǎng)絡,下載圖片,并且展示 netCacheUtil.display(imageView, url,lv_photo_list); } }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
ListView實現(xiàn)聊天列表之處理不同數(shù)據(jù)項
這篇文章主要為大家詳細介紹了ListView實現(xiàn)聊天列表之處理不同數(shù)據(jù)項,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11Android自定義有限制區(qū)域的圖例角度自識別涂鴉工具類完結篇
這篇文章主要為大家介紹了Android自定義有限制區(qū)域的圖例角度自識別涂鴉工具類完結篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02Android 中 SwipeLayout一個展示條目底層菜單的側滑控件源碼解析
這篇文章主要介紹了Android 中 SwipeLayout一個展示條目底層菜單的側滑控件源碼解析,需要的朋友可以參考下2016-12-12Android中利用C++處理Bitmap對象的實現(xiàn)方法
下面小編就為大家?guī)硪黄狝ndroid中利用C++處理Bitmap對象的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03Android中如何指定SnackBar在屏幕的位置及小問題解決
這篇文章主要給大家介紹了關于Android中如何指定SnackBar在屏幕的位置,以及一個小問題解決的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2018-03-03Android BottomNavigationView結合ViewPager實現(xiàn)底部導航欄步驟詳解
這篇文章主要介紹了Android BottomNavigationView結合ViewPager實現(xiàn)底部導航欄步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2023-02-02Android TextView 去掉自適應默認的fontpadding的實現(xiàn)方法
這篇文章主要介紹了Android TextView 去掉自適應默認的fontpadding的實現(xiàn)方法的相關資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09