Android圖片加載庫Glide和Fresco是如何工作的

原文地址:https://blog.mindorks.com/how-the-android-image-loading-library-glide-and-fresco-works-962bc9d1cc40

通常,我們在加載圖片的時候經常會遇到如下的問題:

  • 內存溢出錯誤
  • 圖片加載到視圖中比較緩慢
  • UI變得無響應,并且不能平滑滾動

讓我們來看一下它們是如何一個一個解決這些問題的

內存溢出錯誤

Glide做了向下采樣的工作,向下采樣意味著將bitmap縮放到一個視圖實際需要的一個較小的尺寸。更通俗的講就是我們有一個20002000的圖片,但是我們的view大小為400400,Glide就會將我們的圖片縮小為400*400的然后顯示到View中。

Glide知道作為參數傳入的Imageview的大小,所以就會加載合適尺寸的圖片給ImageView。從而不用加載完整的圖片。

加載緩慢

加載緩慢的一個主要問題就是當view被移除的時候,還在進行加載圖片和解碼bitmap的任務,因此就有很多我們不需要的任務在執(zhí)行,而Glide可以適時的停止這些任務,只有在視圖對用戶可見的時候才會去加載圖片。

Glide能夠知道Activity和Fragment的生命周期所以知道下載任務什么時候需要被取消掉。

另外一個方式就是內存緩存,我們不用一遍又一遍的解碼bitmap從而節(jié)省了時間。Glide創(chuàng)建一些可配置大小的緩存來捕獲圖片。

它保持兩級的緩存:

  • 內存緩存
  • 磁盤緩存

當我們給Glide提供一個Url的時候,他會做如下操作:

  • 他會檢查以該url為key的圖片是否存在于內存緩存中,并且是否可用
  • 如果存在于內存緩存中,他就會從內存緩存中取出加載到view中
  • 如果當下不在內存緩存中,就會去檢查磁盤緩存
  • 如果存在于磁盤緩存中,則會取出,然后存儲到內存緩存并且加載到View中
  • 如果也不存在于磁盤緩存的話,他會從網絡上加載,然后存儲到內存和磁盤,并且加載到view中

UI無響應

UI無響應的一個最重要的原因就是在主線程中做了太多的工作,我們知道渲染UI的所有動作都在主線程中完成,Android每16毫秒就會更新一下UI,如果執(zhí)行任何超過16ms的任務,安卓就會跳過該更新,因此就會導致每秒幀數減少。

如果FPS較低,則用戶看到UI就會無響應,即使在后臺線程加載圖片,也還會如此,這是為什么?

因為如果加載的Bitmap太大,他就會導致內存回收頻繁。

當GC運行的時候,應用就無法運行。

Glide如何解決這個問題呢?
使用Bitmap池。
Glide使用Bitmap池的思想來盡量減少GC的執(zhí)行。
如果使用圖片池就會減少內存的分配和釋放,從而實現應用程序的平滑運行。

如何避免在應用程序中持續(xù)分配和釋放內存呢?
通過使用bitmap的inBitmap屬性,他會重用Bitmap的內存。

使用時的一些限制:

在SDK18及以下,加載的位圖和你重新使用的位圖必須大小一致才能正常工作。

在SDK19及以上,規(guī)則則會稍微放松一些,你的現有的位圖可以比要加載的位圖大或者相同。

對于不同的像素格式使用不同的位圖。

如果我們需要一個接一個的加載兩張圖片,加載第一張的時候會分配內存,當我們不需要第一張的時候,不需要回收bitmap,使用第一張圖片的內存來加載第二張圖片。

接下來看一下代碼:

Bitmap bitmapOne = BitmapFactory.decodeFile(filePathOne);
imageView.setImageBitmap(bitmapOne);
// lets say , we do not need image bitmapOne now and we have to set // another bitmap in imageView
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePathTwo, options);
options.inMutable = true;
options.inBitmap = bitmapOne;
options.inJustDecodeBounds = false;
Bitmap bitmapTwo = BitmapFactory.decodeFile(filePathTwo, options);
imageView.setImageBitmap(bitmapTwo);

這樣我們就不會一次又一次的調用GC。
這里有幾件在不同Android版本中,bubitmap重用時需要考慮的事情.

你可以說bitmap池是不再需要的bitmap列表,但是可以用來重用用以加載新的位圖。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容