客製化 Flutter Image Provider

之前在 flutter app 中使用 Optimized Cached Image 來展示圖片,選擇他的原因也很簡單,因為當時剛學 flutter 沒多久就要直接上陣了。先選一個看起來簡單好用的再說;而且他還可以設置 cache key,避免重複抓取,感覺起來就不錯。

然而後來圖片一多起來之後,就發現問題了,往往 app 打開滑沒幾下就 crash。看 log 是 OOM 問題,上網查了一下,有人說是 memory leak。大致上就是 image disposed 之後,沒有正確的釋放 ram,app 佔用的 ram 越來越多,就直接觸發 OOM killer。測試了一下原生的 NetworkImage 沒有這個問題。所以應該就是 Optimized Cached Image 的問題了。

另外就是在我的程式裡,widget 只拿到 media id,需要先到後端去查 media 的 presigned url 返回給 app,app 再用 presigned url 抓圖片資料。也就是原來的程式碼裡一直都是 future builder + image,這造成的問題就是頁面一刷新就要重新抓 presigned url,大大降低了效率,也大大提升了後端的負載。

因此決定客製化一個業務專用的 image provider。

經一番 google 之後,找到了一篇寫得很淺顯易懂的文章: Flutter 网络图片的缓存和加载

按他的方法客製了一個自己的版本,目標:

  1. 使用 ffcache 做圖片快取存儲,如果 cache 中有圖片的資料,就直接讀取 cache;如果 cache 沒有,就從網路上下載。
  2. 將查詢業務 media 資料的程式邏輯放到 image provider 中自動查詢,一方面簡化輸入的參數,另一方面 widget 無需再用 future builder,減少 rebuild 過程中無意義的消耗。

以下展示程式碼:

這樣就可以用了。使用的方式:

Image(
    image: MyImageProvider(media: data),
    fit: BoxFit.cover,
);

或:

Container(
    decoration: BoxDecoration(
      image: DecorationImage(
          image: MyImageProvider(media: data),
          fit: BoxFit.cover,
      ),
    ),
);