🧠 核心思路總結
??徹底繞過?Image
組件重建帶來的性能瓶頸??:不再讓?setState
重建包含?Image
的 Widget 樹(這是開銷大、可能導致閃爍的根源),改為使用底層畫布 (Canvas
) 直接繪制預先處理好的圖像幀數據。
好的,我來幫你清晰、簡潔地總結一下你提出的 ??Flutter GIF 序列幀動畫閃爍解決方案(使用?CustomPaint
)?? 的核心要點:
🧠 核心思路總結
??徹底繞過?Image
組件重建帶來的性能瓶頸??:不再讓?setState
重建包含?Image
的 Widget 樹(這是開銷大、可能導致閃爍的根源),改為使用底層畫布 (Canvas
) 直接繪制預先處理好的圖像幀數據。
💡 核心改進點總結(方案精髓)
??👉 高效預加載:??
??做什么??? 在?
initState
中,??預先將 GIF 的所有幀?? (AssetImage
或其他來源) ??解碼??成?ui.Image
對象。??為什么????
ui.Image
是 Flutter 渲染引擎直接使用的底層圖片格式,內存駐留,??避免運行時重復解碼帶來的卡頓和延遲??。將它們??緩存??在內存中(如?List<ui.Image>
)。
??👉 專用繪制器:??
??做什么??? 創建一個繼承自?
CustomPainter
的類(例如?_EarthPainter
)。??做什么??? 在這個類的?
paint
方法中,接收??當前應該顯示的幀索引(或?ui.Image
對象)??,并調用?canvas.drawImage
(或?drawImageRect
) 方法??直接將對應的?ui.Image
繪制到畫布上??。??為什么????
CustomPainter
非常輕量,它的?paint
調用是 Flutter 渲染管線中優化非常好的部分。僅繪制一個位圖 (ui.Image
) 到畫布上??性能開銷極低??。
??👉 輕量級狀態更新:??
??做什么??? 使用?
CustomPaint
Widget 作為地球動畫的容器,將上面創建的?_EarthPainter
實例傳入。??做什么??? 當需要切換到下一幀動畫時,??只更新?
_EarthPainter
內部存儲的?當前幀索引
(或?當前幀的ui.Image
) 狀態??。??做什么??? ??通知?
CustomPaint
需要重繪??(通過?ChangeNotifier
或簡單地標記?_EarthPainter
實例為?shouldRepaint
)。??為什么??? 這個更新??只觸發?
paint
方法的再次調用??(在?CustomPaint
范圍內),??完全不涉及重建上層 Widget 樹 (如?Image
,?Container
,?Stack
等組件)??。??大大減少了渲染開銷。?
📝 簡明提示詞(Action Plan)
??預加載和解碼:???
initState
中加載GIF,??將所有幀解碼并緩存為List<ui.Image>
??。??創建繪制器:?? 寫一個
CustomPainter
子類(_EarthPainter
)。它持有:緩存的幀列表 (
List<ui.Image>
)。當前幀索引
(int) 或?當前幀Image
(ui.Image?)。paint
方法中:canvas.drawImage(_cachedFrames[currentIndex], ...)
。
??使用
CustomPaint
:?? 在?connectWidget
/disconnectWidget
等位置,用?CustomPaint(painter: _EarthPainter(...))
替代原來的?Image
組件。??驅動動畫:?? 使用?
AnimationController
+?Ticker
/Timer
按幀率 (如 24 fps) ??只更新?_EarthPainter
的?當前幀索引
?? 并調用?painter.markNeedsPaint()
或更新?CustomPaint
的?painter
引用(觸發?shouldRepaint
邏輯)。