Flutter應(yīng)用如何調(diào)試–DevTools介紹(上)
Flutter應(yīng)用如何調(diào)試–DevTools介紹(中)
Flutter應(yīng)用如何調(diào)試–DevTools介紹(下)
Dart DevTools主要有7個(gè)工具,其中Flutter inspector與Debugger只能在debug模式下查看,Timeline、Memory、Performance更傾向于在Profile模式下使用,Network、Logging則無(wú)模式要求,下面將對(duì)它們進(jìn)行詳細(xì)介紹,如有疏漏或者錯(cuò)誤,歡迎與我聯(lián)系交流。
- Flutter inspector
- Timeline
- Memory
- Performance
- Debugger
- Network
- Logging
1、Flutter inspector工具
簡(jiǎn)介:inspector是用于可視化和瀏覽Flutter小部件樹(shù)的強(qiáng)大工具,用來(lái)可視化和瀏覽Flutter widget trees,以便:
- 了解現(xiàn)有布局
-
診斷布局問(wèn)題
Flutter inspector運(yùn)行在debug模式下。
inspector.png
除了在網(wǎng)頁(yè)上查看,F(xiàn)lutter inspector還可以在Android Studio的右側(cè)區(qū)域進(jìn)行插查看

兩者本質(zhì)上沒(méi)有太大區(qū)別,IDE中多了一個(gè)查看Render Tree的入口,網(wǎng)頁(yè)上則可以對(duì)布局進(jìn)行調(diào)試,并且視圖窗口更大,除此之外沒(méi)有太大區(qū)別。
Select Widget Mode
我們開(kāi)發(fā)Flutter應(yīng)用,知道Widget的設(shè)計(jì)理念是組合大于繼承,一層層的Widget嵌套,使得排查Flutter widget trees的時(shí)候,也往往受制于嵌套,有了inspector工具可以使得我們一步即可找到widget trees的對(duì)應(yīng)節(jié)點(diǎn)。勾選中途中紅色的第一個(gè)控件Select Widget Mode,我們可以再手機(jī)屏幕上選中想要查看的組件,或者選中widget trees中的節(jié)點(diǎn),然后就是令人激動(dòng)的功能:手機(jī)屏幕中、代碼中、DevTools中,相應(yīng)的地方也都會(huì)自動(dòng)同步,方便我們定位問(wèn)題,在Detail Tree中我們還可以看到選中widget的詳細(xì)屬性。


另一個(gè)令人激動(dòng)的點(diǎn)是,我們可以不用修改代碼就可以對(duì)布局進(jìn)行調(diào)整,這就是動(dòng)態(tài)調(diào)試
Layout Explorer,可以改變主軸方向,flex權(quán)重等屬性。
Slow Animation
當(dāng)我們調(diào)試動(dòng)畫(huà)的時(shí)候,會(huì)希望動(dòng)畫(huà)慢點(diǎn)播放,就像iOS模擬器支持的Slow Animation一樣,inspector工具的Slow Animation也支持將動(dòng)畫(huà)速度放慢5倍,如過(guò)希望自定義的話(huà)可以通過(guò)編碼的方式,設(shè)置timeDilation屬性,最多支持1到50倍慢放。
其它選項(xiàng)
-
Refresh Tree可以刷新當(dāng)前widget信息 -
Debug Paint在頁(yè)面上添加一些調(diào)試樣式,以顯示邊框,填充,對(duì)齊和間隔,如下圖 -
Paint Baselines則會(huì)使每個(gè)RenderBox在其每個(gè)文本基線(xiàn)處繪制一條線(xiàn)。 -
Repaint Rainbow重繪時(shí)在圖層上顯示旋轉(zhuǎn)顏色。 -
Debug Banner即使運(yùn)行調(diào)試版本,也可以切換調(diào)試標(biāo)語(yǔ)的顯示。
inspector5.jpeg
2、Timeline工具
Timeline需要在profile模式下運(yùn)行,否則不能準(zhǔn)確地統(tǒng)計(jì)APP真是的性能。

首先對(duì)上面四個(gè)按鈕進(jìn)行介紹:
Refesh,滑動(dòng)手機(jī)APP,然后點(diǎn)擊refresh,則會(huì)在下方顯示剛才一段時(shí)間內(nèi)的幀圖(圖中柱狀部分)和火焰圖(圖中中間區(qū)域)。
Profile granularity也叫分析粒度,默認(rèn)樣本室250微妙采樣一次,即medium,采樣率低中高分別對(duì)應(yīng)抽樣率低、中、高粒度分別順序?qū)?yīng) 1/50μs、1/250μs 和 1/1000μs,正確的設(shè)置此粒度對(duì)性能分析非常總要,高粒度 的配置會(huì)具有更高的采樣率,采集信息更多,甚至于VM被中斷以收集采集樣本,導(dǎo)致性能下降。
Performance Overlay即性能圖層,選中之后會(huì)在APP上顯示兩張圖標(biāo)顯示性能信息

如圖所示,最頂部的圖形表示 raster 線(xiàn)程所花費(fèi)的時(shí)間,底部的圖表顯示了 UI 線(xiàn)程所花費(fèi)的時(shí)間。縱軸表示每一幀花費(fèi)時(shí)間,而橫軸則表示幀。只有當(dāng)你的應(yīng)用繪制時(shí)這個(gè)圖表才會(huì)更新,所以如果它空閑的話(huà),圖表就不會(huì)動(dòng)。圖中的綠色豎條表示當(dāng)前幀,為綠色表示性能良好,為紅色則表示出現(xiàn)了卡頓,如果是在 UI 圖表出現(xiàn)了紅色豎條,則表明 Dart 代碼消耗了大量資源。而如果紅色豎條是在 GPU 圖表出現(xiàn)的,意味著場(chǎng)景太復(fù)雜導(dǎo)致無(wú)法快速渲染。
Flutter線(xiàn)程
這里對(duì)Flutter的線(xiàn)程做簡(jiǎn)單說(shuō)明,F(xiàn)lutter使用多個(gè)線(xiàn)程來(lái)完成其工作,盡管覆蓋圖中僅顯示了兩個(gè)線(xiàn)程。您所有的Dart代碼都在UI線(xiàn)程上運(yùn)行。盡管您沒(méi)有直接訪問(wèn)任何其他線(xiàn)程的權(quán)限,但是您對(duì)UI線(xiàn)程的操作會(huì)對(duì)其他線(xiàn)程產(chǎn)生性能影響。
-
Platform thread也叫平臺(tái)線(xiàn)程,plugin的代碼將會(huì)運(yùn)行在這里,對(duì)應(yīng)Android和iOS的主線(xiàn)程MainThread -
UI threadUI 線(xiàn)程在 Dart VM 中執(zhí)行 Dart 代碼。該線(xiàn)程包括開(kāi)發(fā)者寫(xiě)下的代碼和 Flutter 框架根據(jù)應(yīng)用行為生成的代碼。當(dāng)應(yīng)用創(chuàng)建和展示場(chǎng)景的時(shí)候,UI 線(xiàn)程首先建立一個(gè) 圖層樹(shù)(layer tree) ,一個(gè)包含設(shè)備無(wú)關(guān)的渲染命令的輕量對(duì)象,并將圖層樹(shù)發(fā)送到 GPU 線(xiàn)程來(lái)渲染到設(shè)備上。 不要阻塞這個(gè)線(xiàn)程! 在性能圖層的最低欄展示該線(xiàn)程。 -
Raster thread(以前叫 GPU 線(xiàn)程),中文名字叫光柵線(xiàn)程或者柵格線(xiàn)程,raster 線(xiàn)程拿到 layer tree,并將它交給 GPU(圖形處理單元)。你無(wú)法直接與 GPU 線(xiàn)程或其數(shù)據(jù)通信,但如果該線(xiàn)程變慢,一定是開(kāi)發(fā)者 Dart 代碼中的某處導(dǎo)致的。圖形庫(kù) Skia 在該線(xiàn)程運(yùn)行,并在性能圖層的最頂欄顯示該線(xiàn)程。這個(gè)線(xiàn)程之前被叫做 “GPU 線(xiàn)程”,因?yàn)樗鼮?GPU 進(jìn)行柵格化,但我們重新將它命名為 “raster 線(xiàn)程”,這是因?yàn)樵S多開(kāi)發(fā)者錯(cuò)誤的(但是能理解)認(rèn)為該線(xiàn)程運(yùn)行在 GPU 單元。 -
I/O thread執(zhí)行昂貴的操作(常見(jiàn)的有 I/O)以避免阻塞 UI 或者 raster 線(xiàn)程。這個(gè)線(xiàn)程將不會(huì)顯示在 performance overlay 上。
除此之外我們分析Flutter APP的時(shí)候,應(yīng)該在真機(jī)上,并且最好用性能較差的機(jī)型去多次分析。在分析性能的時(shí)候,不應(yīng)只局限于當(dāng)前設(shè)備運(yùn)行流暢。
- 將幀渲染時(shí)間降低到 16ms 以下可能在視覺(jué)上看不出來(lái)什么變化,但可以延長(zhǎng)電池壽命以及避免發(fā)熱問(wèn)題。
- 可能在你當(dāng)前測(cè)試設(shè)備上運(yùn)行良好,但請(qǐng)考慮在應(yīng)用所支持的最低端設(shè)備上的情況。
- 當(dāng) 120fps 的設(shè)備普及之后,便需要在 8ms 之內(nèi)完成每一幀的渲染來(lái)保證流暢平滑的體驗(yàn)。
好了基本概念介紹完了,我們繼續(xù)介紹Timeline的使用
幀圖中的每一個(gè)豎條都是可以點(diǎn)擊的,點(diǎn)擊周后,下面的火焰圖相應(yīng)的幀也會(huì)隨之選中,在火焰圖中我們可以分析UI線(xiàn)程和Raster線(xiàn)程,可以對(duì)其進(jìn)行單指上下左右滑動(dòng),也可以雙指進(jìn)行放大縮小。
Track Widget Builds,Timeline中的最后一個(gè)按鈕,這個(gè)按鈕選中的時(shí)候,可以在火焰圖中的UI幀中看到具體是用戶(hù)寫(xiě)的哪一個(gè)widget,如果這個(gè)widget占用時(shí)間過(guò)多的話(huà),我們就可以針對(duì)行的進(jìn)行優(yōu)化,如上面的圖中所示KnowlwdgeCellWidget的創(chuàng)建花了4.5ms,點(diǎn)擊選中它,在視圖的地步還會(huì)顯示CPU Flame Chart、Call Tree、Bottom Up這里先不做介紹,會(huì)在Performance進(jìn)行講述。
Memory
內(nèi)存分析可以幫助我們查看在某一時(shí)刻內(nèi)存使用情況,能夠具體到某個(gè)類(lèi)使用了多少內(nèi)存,主動(dòng)觸發(fā)垃圾回收等。

默認(rèn)進(jìn)來(lái)的時(shí)候只有圖中藍(lán)色的區(qū)域,點(diǎn)擊
Android Menory也會(huì)顯示,當(dāng)鼠標(biāo)點(diǎn)擊圖標(biāo)的時(shí),會(huì)顯示一個(gè)浮動(dòng)窗口,顯示內(nèi)存使用具體數(shù)值。
Snapshot單擊Snapshot按鈕,會(huì)顯示當(dāng)前內(nèi)存對(duì)象表??梢园搭?lèi)名稱(chēng),大小,分配的實(shí)例等對(duì)內(nèi)存對(duì)象進(jìn)行排序。還可以點(diǎn)擊右側(cè)進(jìn)行搜索。
如圖中,選中了d_stack進(jìn)行分析,右側(cè)是d_stack框架中Flutter側(cè)的,DStack類(lèi)占用的內(nèi)存,甚至可以看到內(nèi)存中存儲(chǔ)了哪些數(shù)據(jù)。
我們可以在Search直接搜索想要查看的類(lèi),方便快速查找。
除了看數(shù)據(jù)列表,我們還可以以堆棧視圖的方式查看內(nèi)存分布,當(dāng)我們選中Heat Map開(kāi)關(guān)的時(shí)候,下面會(huì)呈現(xiàn)內(nèi)存視圖,下面區(qū)域是上面的總和,鼠標(biāo)放在某一個(gè)塊中,當(dāng)前塊會(huì)展開(kāi)為更細(xì)粒度的使用情況,如下圖

也可以對(duì)堆棧信息進(jìn)行搜索,方便快速查看

受限于篇幅,本篇就介紹到這里,剩下的
- Performance
- Debugger
- Network
- Logging
留到Flutter應(yīng)用如何調(diào)試--DevTools介紹(下)介紹。

