Flutter圖片緩存管理ImageCache原理分析
引言
設計: 嗯? 這個圖片點擊跳轉(zhuǎn)進詳情再返回圖片怎么變白閃一下呢?
產(chǎn)品: 是啊是啊! 一定是個bug
開發(fā): 囧囧囧
在開發(fā)過程中, 也許你也遇到過這樣一個場景. 進入一個頁面后,前一個頁面的圖片都會閃白一下. 或者在列表中,加載很多列表項后,之前列表中的圖片都需要重新加載.你有沒有想過這一切的原因是什么呢?
沒錯! 它就是我們今天介紹的主人公 --- ImageCache
可能有些人對ImageCache還有些陌生, 我們在之前的章節(jié)有說過啟動流程時Flutter runApp到渲染上屏,有介紹過其中PaintingBinding這個mixin類.帶著探索的心我們先去看看PaintingBinding都做了 一些什么操作呢?
PaintingBinding
PaintingBinding在構造函數(shù)中,除了構建自身的實例.同時也構建了圖片緩存的管理實例.也包括了著色器預熱.
{ _instance = this; // 創(chuàng)建了圖片緩存管理 _imageCache = createImageCache(); shaderWarmUp?.execute(); }
著色器預熱可能大部分人都沒有接觸過,我們只需要知道通過著色器預熱,可以提高首次編譯的速度即可.有興趣可以看一下這篇文章著色器預熱; 我們現(xiàn)在把目光重新聚焦到今天的主題, 也就是createImageCache()這里.可以看到它直接返回了一個ImageCache的對象. 這里我們暫且不談ImageCache, 再去看看在PaintingBinding有沒有和ImageCache相關的一些代碼吧.
@override void evict(String asset) { // 調(diào)用了rootBundle.evict(asset); // 也就是從緩存中移除這個key的資源 super.evict(asset); // 清除所有已顯示和不再用到的圖片緩存 imageCache.clear(); // 清除所有實時引用的圖片緩存 imageCache.clearLiveImages(); } @override void handleMemoryPressure() { // rootBundle.clear(); // 當操作系統(tǒng)通知應用程序內(nèi)存壓力情況時調(diào)用。 // 清除所有的圖片資源 super.handleMemoryPressure(); imageCache.clear(); }
可以看到, 基本上所有的引用都避不開內(nèi)存問題. 也就是文章開頭出現(xiàn)的bug. 那么,為什么會出現(xiàn)閃白呢? 有多種可能,有可能是系統(tǒng)感受到了內(nèi)存壓力調(diào)用了handleMemoryPressure() 方法,清除了圖片緩存,或者在ImageCache中,達到了最大緩存,因此內(nèi)部根據(jù)least-recently-used的原則回收了圖片緩存.所以回頭再看的時候,圖片又重新加載了一遍.自然發(fā)生了閃白現(xiàn)象. 既然知道了原因,那么解決問題的方法:
- 減少圖片緩存
- 增大圖片緩存的閥值,讓系統(tǒng)感覺到壓力的閥值提升 我們來分別分析一下兩者的可行性
減少圖片緩存
如果要減少圖片緩存, 我們要知道圖片的內(nèi)存是怎么計算的? 圖片內(nèi)存=分辨率*每個像素點大小 減少的方法也就出來了:
- 減少分辨率
也就是降低采樣率.flutter中即cacheHeight和cacheWidth - 減少像素點大小
這里也就是像素點的格式,ALPHA_8、RGB_565、ARGB_4444、ARGB_8888、RGBA_F16這些
增大閥值
這里需要去看一下ImageCache中.我們推斷一下,什么情況下一個緩存池會達到閥值呢? 那一定是有新圖片插入,所以總量才會提升才會夠到閥值的門檻.我們找一下有沒有相關的方法. 嗯哼~ 果然有一個_checkCacheSize
{ ... // 只要當前的內(nèi)存超標就會一直執(zhí)行下去 while (_currentSizeBytes > _maximumSizeBytes || _cache.length > _maximumSize) { // 根據(jù)least-recently-used這個邏輯去依次清除圖片緩存 final Object key = _cache.keys.first; final _CachedImage image = _cache[key]!; _currentSizeBytes -= image.sizeBytes!; image.dispose(); _cache.remove(key); } ... }
說明我們閥值取決于_maximumSizeBytes和_maximumSize, 一個負責最大緩存圖片內(nèi)存,一個負責最大緩存圖片數(shù). 也就是說我們更新這兩個指就可以改變圖片內(nèi)存的閥值.從而減少內(nèi)存回收的頻率.
思考
很多問題的發(fā)生實際上源碼中都有些提示, 帶著問題去看收獲的遠遠比單獨閱讀源碼要有收獲的多.
這里是weniner,一個在奮斗的flutter. 有些收獲的話,不妨點個關注哦!
以上就是Flutter圖片緩存管理ImageCache原理分析的詳細內(nèi)容,更多關于Flutter ImageCache的資料請關注腳本之家其它相關文章!
相關文章
Android中自定義ImageView添加文字設置按下效果詳解
這篇文章主要給大家介紹了關于Android中自定義ImageView添加文字設置按下效果的相關資料,實現(xiàn)后的效果非常利用用戶的體驗,文中給出了詳細的示例代碼供大家參考學習,需要的朋友們下面隨著小編來一起學習學習下吧。2017-08-08android實現(xiàn)圖片上傳功能(springMvc)
這篇文章主要為大家詳細介紹了android結合springMvc實現(xiàn)圖片上傳的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Android中自定義View的實現(xiàn)方式總結大全
這篇文章主要總結了Android中自定義View的實現(xiàn)方式的相關資料,文中介紹的非常詳細,對各位Android開發(fā)者們學習或者使用自定義View具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-04-04Android ExpandableRecyclerView使用方法詳解
這篇文章主要為大家詳細介紹了Android ExpandableRecyclerView的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08Android ActionBar完全解析使用官方推薦的最佳導航欄(上)
Action Bar是一種新増的導航欄功能,在Android 3.0之后加入到系統(tǒng)的API當中,它標識了用戶當前操作界面的位置,并提供了額外的用戶動作、界面導航等功能2017-04-04android 實現(xiàn)APP中改變頭像圖片的實例代碼
這篇文章主要介紹了android 實現(xiàn)APP中改變頭像圖片的實例代碼,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07