Glide優化


幾乎所有的 OOM 錯誤都是因為宿主應用出了問題,而不是 Glide 本身。 應用里兩種常見的 OOM 錯誤分別是:
過大的內存分配 (Excessively large allocations)
內存泄露(Memory leaks, 被分配的內存沒有被釋放)

  • 引入largeHeap屬性,讓系統為App分配更多的獨立內存。
  • 禁止Glide內存緩存。設置skipMemoryCache(true)。
  • 自定義GlideModule。設置MemoryCache和BitmapPool大小。
  • 升級到Glide4.0,使用asDrawable代替asBitmap,drawable更省內存。
  • ImageView的scaleType為fitXY時,改為fitCenter/centerCrop/fitStart/fitEnd顯示。
  • 不使用application作為context。當context為application時,會把imageView是生命周期延長到整個運行過程中,imageView不能被回收,從而造成OOM異常。
  • 使用application作為context。但是對ImageView使用弱引用或軟引用,盡量使用SoftReference,當內存不足時,將及時回收無用的ImageView。
  • 當列表在滑動的時候,調用Glide的pauseRequests()取消請求,滑動停止時,調用resumeRequests()恢復請求。
if (view.getContext() != null) {
        switch (scrollState) {
            case SCROLL_STATE_IDLE:
                Glide.with(view.getContext()).resumeRequests();
                break;
            case SCROLL_STATE_TOUCH_SCROLL:
            case SCROLL_STATE_FLING:
                Glide.with(view.getContext()).pauseRequests();
                break;
        }
    }
  • Try catch某些大內存分配的操作。考慮在catch里面嘗試一次降級的內存分配操作。例如decode bitmap的時候,catch到OOM,可以嘗試把采樣比例再增加一倍之后,再次嘗試decode。
  • BitmapFactory.Options和BitmapFactory.decodeStream獲取原始圖片的寬、高,繞過Java層加載Bitmap,再調用Glide的override(width,height)控制顯示。
  • 圖片局部加載。參考:SubsamplingScaleImageView,先將圖片下載到本地,然后去加載,只加載當前可視區域,在手指拖動的時候再去加載另外的區域。
  • onTrimMemory,調用 Glide.cleanMemroy() 清理掉所有的內存緩存。(內部是LruBitmapPool )
  • 如果是處於 lowMemory 的時候,將圖片的 DecodeFormat 設置為 RGB_565
  • 使用glide自己的圓角圖片。bitmapTransfrom

優化GIF

FrameSequence是Android framework中里的一個工具包。 它封裝了: giflib (gif編解碼庫c++ ),並提供Java API播放gif。使用它要比glide加載GIF效果效果要好,glide加載加載GIF圖片CPU占用高,並且內存占用一直在增加。使用FrameSequence庫就可以解決,不過每次判斷去怎么加載很麻煩,可以使用glide的AppGlideModule apt注解解析器來自動生成代碼。判斷GIF圖片時將InputStream轉成FrameSequenceDrawable解析。這個還可以做播放Webp動畫。

@GlideModule
public class GifGlideModule extends AppGlideModule {
    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
        super.registerComponents(context, glide, registry);
        registry.append(Registry.BUCKET_GIF,
                InputStream.class,
                FrameSequenceDrawable.class, new GifDecoder(glide.getBitmapPool()));
    }
}

Glide加載Gif圖片的原理:將gif根據每一幀解析成很張圖片,然后在依次設置給ImageView。

FrameSequenceDrawable原理
利用了兩個Bitmap對象,其中一個用於繪制到屏幕上,另外一個用於解析下一張要展示的圖片,利用了HandlerThread在子線程解析,每次解析的時候獲取上一張圖片的展示時間,然后使用Drawable自身的scheduleSelf方法在指定時間替換圖片,在達到替換時間時,會調用draw方法,在draw之前先去子線程解析下一張要展示的圖片,然后重復這個步驟,直到播放結束或者一直播放。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM