iT邦幫忙

0

Android Image Out of Memory處理

先來介紹個最基本的原理

未來圖片照片解析度越來越高,這是不變的真理以前一千萬畫素可以拿出來大打廣吿,今年好像看到了一億畫素

現今一般中階、高階手機解析度大概都在1920x1080,神一點的或許在3040x1440,但隨便一台手機拍出的照片幾乎鬥超過這個解析度,既然手機螢幕無法展示完整圖片解析度的效果,那為何要花這麼多資源把圖片載下來

所以我們的Google大哥一早直接把程式碼貼出來給你抄了
https://developer.android.com/topic/performance/graphics/load-bitmap

按照文檔的說明,主要目的是要在讀出圖片時直接壓縮到接近View的尺寸,這樣就可以省掉很多的資源

但是按照文檔做完大概只是第一步,這邊只有教你怎麼節省,當圖片很多,例如在List中呈現數十張的圖片,仍有可能會爆炸,所以會需要一個記憶體管理的機制來協助你解決問題

這時候Google大哥又出現了,沒錯就是這個LruCache
https://developer.android.com/reference/android/util/LruCache

Lru就是Least Recently Used縮寫,顧名思義就是最近最沒用到的
把你下載下來的Bigmap賦予一個String(類似ID不重複)放在LruCache中
請他來幫你管理記憶體

走到這裡就有一個基本的雛形,但仍然不夠好

想想畫面的實際狀況,假設一個List畫面顯示了100圖,讀取1~100圖都還在記憶體足夠的範圍內
List往下滑讀取101~200張圖的時候因為記憶體不足,LruCache幫你回收掉1~100
這時候再拉上去看

哇靠不就全部都要重新載入,要再等一次流量及讀取時間了嗎
這樣使用者體驗肯定不好

所以再加上一個Local storage的機制吧
我們把下載下來的圖片實體存在手機內,用樣類似Lru的機制儲存以及讀取
這樣我們拉回到1~100時優先讀取手機內存的圖片,不用消耗網路流量,速度絕對是大幅上升

有個前提是,不同張的圖片不能用同一個命名,不過通常在Server存取圖片時,每張照片都有唯一值,並不會用取代的方式,所以通常不會有問題產生

講到這裡要去實作大概都想去洗洗睡了

重點來了

其實這些事打從你還在娘胎中就有神幫你做好了,很多的Open Source想得非常周到
這邊我們就來比較幾款優質的Image Loading Third Party

Glide / Picasso / Fresco

參考一下表格內容
https://ithelp.ithome.com.tw/upload/images/20200430/20126774qfijDv53pX.png

參考網友實測的回報,以及我爬文找到的比較
https://www.quora.com/Which-is-the-fastest-Image-Loading-Library-For-Android

  • Picasso will cache only single size of image, the full-size one
  • Glide needs to be downloaded once again before be resized to the right resolution and then be cached.
  • Fresco, test by myself, looks like download only one time

比較的狀況是,如果有兩個位置顯示同一張圖,但顯示不同的大小
Picasso會直接下載一次,後續可能拿這張圖按照基本原理的方式去讀取
Glide則會下載兩次,存成兩個解析度的圖片
Fresco則是下載一次,但是什麼尺寸這邊並沒有提到,估計應該也是存有壓縮過的

我個人是最喜歡用Fresco,但是引用起來挺肥大的


尚未有邦友留言

立即登入留言