原文連接html
首先,在作性能調優以前,咱們應該對flutter相關基礎知識有必定的瞭解,否則咱們無從作起,首先,咱們要了解flutter是幹嗎的--Flutter 是谷歌2018年發佈的跨平臺移動UI框架。android
而後,他相對於其餘跨平臺開發框架來講,是高效的,至於他爲何高效,緣由是由於:算法
他是直接調用Skia框架,而其餘框架須要藉助現有的原始框架來轉一下,在纔開始去調用Skia框架,這一來二去,確定就有所消耗,這是其一,而後,咱們還須要知道flutter的四個線程。api
分別是:性能優化
該平臺的主線程。插件代碼在這裏運行。更多信息請參閱:iOS 的程序 (UIKit) 文檔,或者 Android 的主線程 (MainThread) 文檔。性能圖層並不會展現該線程。bash
UI 線程在 Dart VM 執行 Dart 代碼。該線程包括開發者寫下的代碼和 Flutter 框架根據應用行爲生成的代碼。當應用建立和展現場景的時候,UI 線程首先創建一個 圖層樹(layer tree) ,一個包含設備無關的渲染命令的輕量對象,並將圖層樹發送到 GPU 線程來渲染到設備上。不要阻塞這個線程!在性能圖層的最低欄展現該線程。app
GPU 線程取回圖層樹並通知 GPU 渲染。儘管沒法直接與 GPU 線程或其數據通訊,但若是該線程變慢,必定是開發者 Dart 代碼中的某處致使的。圖形庫 Skia 在該線程運行,有時也被叫作光柵器 (rasterizer) 線程。在性能圖層的最頂欄顯示該線程。框架
可能阻塞 UI 或者 GPU 線程的耗時任務(大多數狀況下是 I/O)。該線程並不會在性能圖層中展現。函數
因此,咱們作性能優化,關心DartUI,關心GPU兩個線程,掉不掉幀,卡不卡的關鍵,就看這兩位了,並且在99%狀況下,做爲Flutter開發人員,咱們咱們基本上解決好,DartUI線程上的問題,就==解決了渲染性能問題。工具
爲了更加直觀的表示3個樹的從生到死,我不得不拋出下面這幅圖來
而後,咱們常常在作性能調優的時候,會用到timeline工具,你會看到這樣一幅圖:
如今串起來了嗎,4個線程,build---layout---paint三個階段是否是都一目瞭然,各發生在什麼地方,什麼階段,誰先誰後。
因此,咱們說 要解決卡頓掉幀的問題,就是要解決build,layout,paint這三個階段各函數執行耗時的問題。
首先,咱們配置下環境,這裏我配置這個變量debugProfileBuildsEnabled=true
否則,我不知道build他具體作了些啥,觀望臺默認不會告訴我。通常來講,放在main函數中,在runApp以前開啓便可,好比我是這麼幹的:
這裏面有一些其餘須要用到的開關,能夠在數據不足的時候開啓,這樣咱們參考的數據多些,優化的參考點就明確些。
而後,咱們執行 flutter run --profile ,請記住,咱們須要在profile模式來性能調優,debug模式由於在渲染過程當中記錄了不少分析數據且加上支持熱重載的特性是損失了不少性能爲代價的,profile模式更加接近release模式性能。
而後跑起來了,會出現一個連接:
點一下就去了觀望臺了,固然,你也可使用devTools,貌似後面會取代觀望臺。devTools的啓動姿式是:
flutter pub global activate devtools
devTools複製代碼
先安裝,而後在直接運行便可:
點擊這個連接,會彈出一個網頁來,讓你輸入url,這個url就是咱們那個觀望臺的url,所以你彷佛秒懂了,然來,devTools是在觀望臺的基礎至上作的一個分析工具,因此,Google必定是以爲觀望臺不大友好了,然而,遺憾的是,devTools並非特別全面,由於如今仍是preview階段嘛,一切都會好起來的。
一般來講,很容易發現有問題的地方,明顯那個會比較寬比較長的地方就比較能夠,這種一遍就能夠定位頁面加載比較慢了,而後咱們點擊向下箭頭,把他放大點看看
大概就看到了,偶,而後,咱們點擊選擇,在選擇一個範圍看看統計效果:
這時候,咱們就發現問題了,而後這個也加載了這麼多個TipCacheNetWorkImage,而後每一個大概要2ms,而後我這個是一個列表頁:
因此,一共就有8個這樣的控件要渲染,而他,就佔用8 *2.188 > 16ms
,所以咱們找到了優化點,解決這個就能夠加速渲染了,這裏只是舉例找到存在性能瓶頸的地方,具體相關函數耗時的優化,相信你們都懂的,這就是算法相關的問題了。
一、儘可能將setState放在葉子節點,好處是build時影響範圍極小,簡稱局部刷新
二、能不用 Opacity
Widget,就儘可能不要用,由於這貨會粗發GPU一個saveLayer的指令,作Skia的大神說,這個指令至關耗時。
三、使用ListView.builder()而不是直接使用ListView()來構建列表。
四、對於頻繁更新的控件(好比倒計時,秒錶),使用RepaintBoundary隔離它,讓他在一個獨立的paint區域。
五、使用const來修飾永遠不須要變動的控件。
六、優先使用StateLessWidget,而不是所有用StateFulWidget
七、使用Visibility控件替換if/else,有些小夥伴喜歡else時return一個 佔位控件,須不知,這種效率是沒有Visibility高效的。
參考資料
調試 Flutter 應用 - Flutter 中文文檔 - Flutter 社區中文資源
files.flutter-io.cn/events/gdd2…