android分享图片功能实现原理,Android:简单实现并理解图片三级缓存
學習Android網絡開發的過程中,勢必會經歷很多痛苦的過程,其中一個大坑就是圖片緩存,當然現在有很多現成的庫非常方便,常常幾行代碼就可以實現想要的功能,但不懂其中的原理是不行的,所以對于剛開始學習網絡編程的小猿們,最好的方法就是手動實現一下。沒有經歷過HttpClient或HttpUrlConnection連接網絡的繁瑣過程,怎么能感受到OkHttp,Volley,Retrofit的方便,下面,我們就一起開始學習圖片三級緩存。
使用圖片緩存的原因
提高用戶體驗:如果每次啟動都從網絡下載圖片,勢必會加載很慢,圖片無法顯示,或需要很久才能完全顯示,用戶體驗及其不好
節約流量:如果每次加載頁面,甚至只是滑動控件瀏覽就會下載的話,會消耗很多流量,占用網絡資源的同時,也會因為應用耗流量而用戶數量級受到影響
什么是三級緩存
內存緩存:優先加載,速度最快
本地緩存:次優先加載,速度較快
網絡緩存:最后加載,速度較慢
緩存策略
為什么使用緩存策略
上面從用戶角度考慮了為什么要使用圖片緩存,此外,從開發人員角度看,Bitmap的創建非常消耗時間和內存,可能導致頻繁GC,使用緩存策略能夠高效加載Bitmap,減少卡頓,從而減少讀取耗時和電量消耗。
緩存策略是什么
具體通過三級級緩存策略,內存作為一級緩存,本地作為二級緩存,網絡直接下載為最后,其實嚴格來說不算緩存。其中內存采用LruCache,其內部通過LinkedhashMap來持有外界緩存對象的強引用;對于本地緩存,我這里為了簡單快速理解原理,直接使用的是文件IO操作,而網上也有人采用DiskLruCache (不是Android官網提供,但被官網推薦)。加載圖片時,首先采用LRU方式進行尋找,若找不到指定內容,則進行本地搜索,若本地也找不到,向網絡發起請求來獲取圖片。
圖片請求緩存框架
調用bindBitmap,傳遞url和ImageView,首先是loadBitmapFromMemCache從內存緩沖區中根據url去找,如果找不到的話,則調用loadBitmap,通過一個runnable,提交到線程池,得到結果后,通過主線程handler來進行ui的更新。這里要注意,當我們加載圖片的時候,如果圖片從內存中找不到,調用了loadBitmap,這個時候,已經將loadbitmap封裝在Runnable中,然后提交到線程池中了,也就是后續的都是和主線程處于異步的狀態同時展開的了,可以很好的解決因為Bitmap的申請創建耗時導致的掉幀現象的出現。
下面是loadBitmap的工作流程:
上圖中,對于loadBitmapFromHttp,在調用的時候,通過urlConnection,將網絡的數據流寫入到本地后,然后又調用的laodBitmapFromDiskCache,也就是在圖片被下載下來之后,首先會將其添加到我們的本地磁盤緩存中,然后當這個圖片被使用的時候,我們又會將其添加到我們的內存緩存中。
以上就是整個圖片請求緩存框架的流程介紹,基本都是按照函數方法的設計進行介紹的,下面就來看看在代碼中,應該如何實現。
圖片緩存代碼實現
首先是整個緩存的函數,相當于前面圖中的 bindBitmap,根據Url來獲取圖片Bitmap。
1、從內存中獲取,函數:loadBitmapFromMemCache,這里用到LruCache,是Android提供的一個緩存工具類,其算法是最近最少使用算法。它把最近使用的對象用“強引用”存儲在LinkedHashMap中,并且把最近最少使用的對象在緩存值達到預設定值之前就從內存中移除。
注意,這里是將url作為key值進行哈希,因為url中可能有特殊字符影響使用,一般采用其MD5值來作為key,我這里沒有實現,只是簡單的將特殊符號進行了替換。
2、從磁盤中加載,函數:loadBitmapFromDiskCache
這里我用了自己寫的工具類FileUtils來進行文件的讀寫,主要包括sd卡的檢查,讀取圖片,存取圖片等操作。注意,若從文件中獲取成功,則將其按照鍵值對的形式存至內存中。
3、從網絡中獲取圖片,函數:loadBitmapFromHttp
同理,這里用了工具類HttpUtils來進行網絡的連接,獲取輸入流InputStream,同時將流直接BitmapFactory.decodeStream轉為Bitmap。若從網絡獲取圖片成功,要將圖片存入磁盤緩存,同時寫入內存。
至此,一個簡易的圖片緩存框架就結束了,但還要注意一下幾點:
Bitmap縮放:從網絡加載過來的圖片我們不可能將其全部加載到內存,需要根據其大小做一個顯示的處理,獲取圖片的寬高,根據控件的寬高進行一個縮放,用BitmapFactory.Options修改其屬性后,設置為該Bitmap的屬性,具體代碼比較容易實現,網上教程較多,這里不再贅述。
AsyncTask線程池問題:這里在實現加載圖片時大多是在多線程中進行的,而android中比較常用比較方便的就是AsyncTask,我按照上述代碼完成后,發現程序加載圖片速度沒有明顯改進,依然會有一個肉眼可見的緩慢過程,經過閱讀源碼發現,雖然利用AsyncTask表面開啟了多個線程,但實際其底層只開了一個單線程順序執行,因而想要同時開啟多個線程下載需要用線程池的方式開啟AsyncTask,具體原因見我上一篇博客
創建類ImageLoader,將imageview,bitmap和url綁定在一起,同時給imageview設置tag進行標記,防止因為異步下載導致的圖片錯位
附上代碼用到的工具類代碼
1、Http工具類
2、File工具類
參考資料
總結
以上是生活随笔為你收集整理的android分享图片功能实现原理,Android:简单实现并理解图片三级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java的reentrantlock_J
- 下一篇: android 本地图片分享,Andro