提高Flutter性能的小技巧!(三)

Yii Chen
7 min readJul 19, 2022

創造高品質的用戶體驗

使用 StatefulBuilder 進行局部更新

  • Widget tree 較大時,更新一個屬性導致整顆樹重建,這是很浪費效能的
  • 使用 builder() 提供的 setState 來更新指定元件,而其他不相關的元件可以保持原樣

補充:適當的搭配 RepaintBoundary 來開發,讓Tree不花費過多成本在重建

適當的壓縮數據

壓縮後可節省記憶體,需要時再解壓縮並使用。

謹慎使用 saveLayer()

  1. 主要是用來呈現各種 UI 視覺效果,渲染形狀、透明度與重疊效果都會使用到 saveLayer()
  2. 調用 saveLayer() 會分配一個 螢幕外緩衝區(offscreen buffer),並且將內容繪製到這裡,可能會觸發渲染目標的切換。渲染目標強制 GPU 臨時轉換工作流,然後再次將其引導回來,影響渲染的效果
  3. 有呼叫 saveLayer() 的元件, ShaderMaskColorFilter
  4. Widgets 跟 Packages 可能有在使用,過多的使用可能造成卡頓

減少裁剪的使用

  1. Clipping 不會調用 saveLayer() (除非使用 Clip.antiAliasWithSaveLayer ),默認情況下裁剪被禁用( Clip.none )
  2. 要創建帶圓角的矩形,可以多使用 borderRadius 屬性去實現,而不要使用裁切矩形
  3. 避免在動畫中進行裁剪,盡量在執行動畫之前先裁剪圖像

在16毫秒內完成創建和顯示幀(Build and display frames)

  1. 創建和渲染在各別的線程上運行,如果要避免延遲,需在16毫秒或更短的時間內創建並顯示一幀。代表著在8毫秒以內創建,並在8毫秒以內渲染。
  2. 如果總渲染時間低於16毫秒,即使存在一些性能缺陷,也不必擔心性能,因為可能不會產生視覺差異
  3. 可以改善電池壽命散熱問題
  4. 隨著120fps設備的普及,需要8毫秒內創建和顯示幀,以提供最流暢的體驗
  5. Flutter Performance 窗口中,開啟 Show widget rebuild information 選項,可幫助檢測幀的渲染和顯示時間是否有超過16毫秒

使用官方的 flutter_lints 套件

  • 隱形的 code reviewer
  • 即時檢查程式碼是否不符合規則、是否有風險、是否需要優化
  • 可以自定義規則,符合自己專案的開發風格
  • 套件持續更新、改版,代表有更強大的審查者在監看,維護專案的高品質

維持 Synchronous BuildContexts

  • 因為UI在 build() 執行時是同步處理,但通常在跟使用者互動後(點擊按鈕…)有可能會觸發非同步任務,如果任務處理完後需要進行一些 context 的存取和操作,必須確保 Widget tree 是否創建完成並與 element 進行綁定,context 本身是 element 的配置
  • 一般畫面、元件在執行動畫、滾動、拖動等操作的時候,Widget會頻繁銷毀跟創建,存活的時間約為50ms,而過程中Widget對應的 element 可能已經離開 element tree,如果在Widget創建期間進行 context 操作,尤其是在非同步任務結束後進行,可能就會出錯和崩潰
  • context操作包含 of(context) 靜態函式的 InheritedWidget 存取

Bad

flutter_lints 會顯示提醒文字,說明不要在執行非同步任務後存取BuildContexts。

Good

需要在存取BuildContexts之前,先透過 mounted 確保(element)已經綁定到 State 上了,如果沒有則不進行後續處理。

還有另一種方式,先儲存需要的物件或資源,等任務處理完後再透過剛剛暫存的物件進行操作。

適當的存取 MediaQuery.of(context)

  • 通常都會在 build() 的一開始取得螢幕長寬,接著設置需要創建的Widget tree,但是只要狀態有更新或是其他原因導致 build() 頻繁重建、更新的話,就會持續存取 MediaQuery。而我們應該只需要在螢幕和畫面大小有變更時重新取得數據就好
  • 一旦 MediaQuery 有任何更新都會觸發 didChangeDependencies(),可以在這裡存取 MediaQuery,取得螢幕大小後儲存到記憶體,接著widget在創建時就可以透過變數取得最新的螢幕數據

補充:當有存取InheritedWidget時,都需要注意操作的地方,避免多餘的成本消耗

保持 Flutter 為最新版本

在每個版本中,Flutter 都進行了許多優化,效能也提高許多,所以不要忘記持續追蹤與更新。

其他文章

關於我

贊助

謝謝你!這是一個很長的文章而且你花費時間看完,真的非常感謝。

還有一件事, 如果覺得文章不錯可以贊助我,讓我有更多的動力和熱情分享 學習筆記和生活!請我喝一杯咖啡吧~

https://www.buymeacoffee.com/yiichenhi

最後

希望有幫助到你/妳,歡迎追蹤我,方便瀏覽最新的文章,也請別忘記給我拍手哦 (最多可以達到50次)!

--

--

Yii Chen

Flutter Lover || Organizer FlutterTaipei || Writer, Speaker || wanna make Flutter strong in Taiwan. https://linktr.ee/yiichenhi