天天看點

Flutter 流暢度優化實踐總結

本篇内容來自ArchSummit會議分享

作者介紹:

張雲龍(雲從),閑魚用戶端專家。先後在網易、位元組、阿裡任職移動端研發。目前在阿裡巴巴閑魚技術部,目前負責閑魚 app 包大小、流暢度、啟動等端體驗内容。

“圍繞 Flutter 流暢度體感優化,分享了挑戰、線上線下監控工具建設、優化手段在元件容器沉澱,最後給出了優化建議。"

大綱

Flutter 流暢度優化實踐總結

本次分享圍繞 flutter 流暢度,分别講述:1.Flutter 流暢度優化挑戰;2.清單容器和 FlutterDx 元件優化;3.性能衡量和 devtool 擴充;4.Flutter 滑動曲線優化;5.性能優化建議。

Flutter 流暢度優化挑戰

▐  業務複雜度挑戰

Flutter 流暢度優化實踐總結
Flutter 一直以高性能被大家所認知,Flutter Gallery(左圖所示)展示的清單控件,也确實非常流暢。但實際業務場景(右圖所示)比 Gallery 清單 demo 複雜的多:

  1. 相同的卡片,有更多和複雜(如圓角)的視圖控件;
  2. 清單滾動時,有更多的視圖邏輯,如滾動控制其他控件漸顯和消失;
  3. 卡片控件,也有更多的業務邏輯,如基于背景資料控制不同的标簽、活動價等,也有埋點等常見業務邏輯;
  4. 因為閑魚是電商 App,是以我們需要有一定的動态能力應對頻繁多變的活動。這裡我們使用阿裡自研的 Flutter DynamicX 元件實作我們的動态能力。

▐  架構實作的挑戰

Flutter 流暢度優化實踐總結

我們再來看清單滾動的整體流程,這裡隻關注手指放開後的自由滾動階段。

  1. 手指松開時,基于 ScrollDragController.end 計算初始速度;
  2. UI Thread 向 Platform Thread 請求 requestFrame,在 Platform Thread 收到 Vsync 資訊,則向 UI Thread 調用 beginFrame;
  3. UI Thread Animate 階段觸發清單滑動一點距離,同時向 Platform Thread 注冊下一幀回調;
  4. UI Thread Build Widget,再通過 Flutter 三棵樹 Diff 算法生成/更新 RenderObject 樹;
  5. UI Thread RenderObject 樹 Layout、Paint 生成 Scene 對象,最後傳遞給 Raster Thread 進行繪制上屏;

上述流程,必須要 16.6 ms 内完成,才能保證不掉幀。大部分情況,不需要建構新的卡片,但當新卡片進入清單區域時,整個計算量就會變得巨大,尤其是在複雜的業務場景下,如何保證在一幀 16.6ms 内完成全部計算,是一個不小的挑戰。

Flutter 流暢度優化實踐總結

上圖是一次滑動 devtool 樣例,卡頓階段都是新卡片上屏時發生,其他階段均很流暢,因為滾動速度在衰減,是以卡頓間隔也在變大。因為大部分時候都很流暢,是以平均 FPS 不低。但新卡片建構時的産生畫面停頓,給我們的卡頓體感卻很明顯。

▐  動态能力的挑戰 - Flutter DynamicX

Flutter 流暢度優化實踐總結

閑魚 App 卡片使用自研 Flutter DynamicX 來支援我們的動态能力。基本原理:線上編輯布局 DSL,生成 dx 檔案并下發。端側通過解析 dx 檔案,并結合背景卡片資料,生成 DXComponentWidget,最後生成 Widget Tree。Flutter DynamicX 技術給閑魚帶來動态更新的能力,統一監控能力(如在 DXComponentWidget 監控卡片建立),良好研發體感(線上 DSL 和 Android Layout 基本一緻,對 Android 開發優化),線上編輯能力;

但在性能上,我們也付出了一定的代價:DX 卡片相比增加了模闆裝載和資料綁定開銷,Widget 要通過 WidgetNode 遞歸周遊動态建立,視圖嵌套層級會更得更深(後續講述)。

說明:Flutter DynamicX 參考阿裡集團 DSL 規則實作

▐  使用者體感的挑戰

Flutter 流暢度優化實踐總結

前面已經講述過,相同 FPS 下,Flutter 清單的卡頓體感更明顯;

在 Android RecycleView 發生小卡頓(16.6*2ms)時,體感并不明顯,而 Flutter 清單在發生卡頓時,不僅時間上停頓,滑動 Offset 上也發生了跳變,為此小卡頓的體感也變得明顯了;

假設清單内容足夠簡單,滾動不會發生卡頓,我們也發現 Flutter 清單和 Android RecycleView 也不太一樣:

  1. 使用 ClampingScrollPhysics,在清單快停止的時候,會感受到類似磁鐵吸住的感覺。
  2. 使用 BouncingScrollPhysics,清單滾動開始時,速度衰減的更快;

在 90hz 機器上,早期 Flutter 清單并不流暢,原因是部分機器上,觸控采樣率是 120hz,螢幕重新整理率是 90hz,導緻部分畫面是 2 次觸控事件,部分是 1 次觸控事件,最後導緻滾動 offset 發生跳變。在 Flutter 1.22 版本時,可以使用 resamplingEnabled 對觸控事件進行重采樣。

清單容器和FlutterDx元件優化

Flutter 流暢度優化實踐總結

講述了 Flutter 流暢度優化的挑戰,現在來分享閑魚如何優化流暢度,并沉澱進 PowerScrollView 和 Flutter Dynamic 元件。

▐  PowerScrollView 設計和性能優化

Flutter 流暢度優化實踐總結

PowerScrollView 是閑魚團隊自研 Flutter 清單元件,在 Sliver 協定上有了更好的封裝和補充:資料增删改方面,補充了局部重新整理;布局方面,補充了瀑布流;事件方面,補充了卡片上屏、離屏、滾動事件;控制方面,補充了滾動到 index 的能力。

在性能方面,補充了瀑布流布局優化、局部重新整理優化、卡片分幀優化和滑動曲線優化。

▐  PowerScrollView 瀑布流布局

Flutter 流暢度優化實踐總結

PowerScrollView 瀑布流布局提供了縱向布局、橫向布局、混排布局(橫向卡片和普通卡片混排)。現在閑魚大部分清單頁面均采用 PowerScrollView 的瀑布流布局,如首頁同城頁、搜尋結果頁等。

▐  PowerScrollView 瀑布流布局優化

Flutter 流暢度優化實踐總結

首先通過正常的緩存優化,緩存每個卡片左上角 x 值和屬于哪一列。

相比 SliverGrid 卡片是并排進入清單區域,而瀑布流布局,我們需要定義 Page,卡片入場建立和離場銷毀需要以 Page 為機關。優化前,Page 以螢幕可視區域為機關計算卡片,同時為了确定 Page 的起點 Y 值,一次布局需要計算 Page N 和 N+1 二頁,是以參與布局計算的卡片量較多,性能變低。優化後,使用全部卡片高度平均值的近似值計算 Page,極大減少參與布局卡片的數量,同時 Page 離場銷毀的卡片數量也變少。

Flutter 流暢度優化實踐總結

經過列緩存和分頁優化,使用閑魚自研 benchmark 工具(後續介紹)對比瀑布流和 GridView,檢視丢幀數和最差幀耗時,能發現性能表現基本一緻。

▐  PowerScrollView 局部重新整理優化

Flutter 流暢度優化實踐總結

閑魚産品期望使用者浏覽商品更流暢,不會被 loadmore 加載打斷,是以清單在滾動過程中就需要觸發 loadmore。Flutter SliverList 在 loadmore 補充卡片資料時,會對 List 控件标髒,而标髒後 SliverList build 會銷毀全部卡片并重新建立,此刻性能資料能想象非常的差。PowerScrollView 提供了布局重新整理優化:緩存螢幕上的全部卡片,不再重新建立,UI Thread 耗時從原來的 34ms 優化至 6ms(見左下圖),右圖檢視 Timeline,視圖建構的深度和複雜度均有明顯優化。

▐  PowerScrollView 卡片分幀優化

Flutter 流暢度優化實踐總結

左圖2個卡片是閑魚早期搜尋結果頁,當時還不是瀑布流。檢視卡片建立時的 Timeline 圖(補充了 Dx Widget 建立 和 PerformLayout 開銷),可以發現一次卡片建立的複雜度極大,在普通中端機器上,UI Thread 耗時機已經超出 30ms,要優化至 16.6ms 以内,用正常的優化手段就很困難了。為此想象 2 個卡片能否拆解掉,各自使用 1 幀的時間去渲染。

Flutter 流暢度優化實踐總結

直接看源碼,基本思想是:對卡片 Widget 進行标記,在左邊卡片真實建立的時候,右邊卡片先 _buildPlaceholderCell 建構占位 Widget(空的 Container),并注冊監聽下一幀。在下一幀,右邊卡片進行修改 needShowRealCell 為 true,并自我标髒,此後建構真實内容。

延遲建構卡片真實内容,是否會對顯示内容産生影響?因為 Flutter 清單在可視區域上下還有 CacheExtends 區域,這部分區域使用者不可見。為此在大部分場景下,使用者并不會看到空白卡片的場景。

同樣使用 Flutter BenchMark 工具進行性能測試,能看到卡片分幀前後 90分位,99分位幀耗時都有明顯的降級,丢幀數也從 39 降低至 27

這裡注意,監聽下一幀的時候,需要 WidgetsBinding.instance.scheduleFrame() 觸發 requestFrame。因為在清單首屏顯示的時候,有可能因為沒有下一幀的回調,導緻延遲顯示隊列的任務沒有執行,最終使得首屏内容顯示不正确。

▐  延遲分幀優化思路和使用建議

Flutter 流暢度優化實踐總結

對比 Flutter 和 H5 設計比較接近:

  1. dart 和 js 都是單線程模型,跨線程通信需要走序列化和反序列化;
  2. Flutter Widget 和 H5 vDom 類似,都有一個 Diff 過程。

早期 FaceBook 在 React 優化時,提出了 Fiber 架構:基于 vDom tree 的父節點→子節點→兄弟節點→子節點的方式,将 vDom tree 轉化為 fiber 資料結構(鍊式結構),進而實作 reconcile 階段的可中斷可恢複;基于 fiber 資料結構,控制部分 fiber 節點在下一幀繼續操作。

基于 React Fiber 思路,我們提出了自己的延遲分幀優化,不隻是左右卡片粒度,更進一步,将渲染内容拆解為目前幀任務、高優延遲任務和低優延遲任務,上屏優先級依次變低。其中目前幀任務,是左右 2 個空白 Container;高優延遲任務獨占一幀,其中圖檔部分也使用 Container 占位;在閑魚場景,我們把全部的 DX Image Widget 從卡片内拆解出來,作為低優延遲任務,并設定在一幀消費不超過 10 個。

通過将 1 幀顯示任務拆解到 4 幀時間,高端機上最高 UI 耗時從 18ms 優化至 8ms。

說明1:不同業務場景下,高優任務和低優任務設定要有所不同 說明2:在低端機(如 vivo Y67)上快速清單滑動,分幀方案會讓使用者看到清單變白和内容上屏的過程

▐  Flutter-DynamicX元件優化-原理詳解

Flutter 流暢度優化實踐總結

線上編輯“類 Android Layout DSL”,編譯生成二進制 dx 檔案。端側通過檔案下載下傳、加載和解析,生成 WidgetNode Tree,見右圖。

Flutter 流暢度優化實踐總結

之後結合背景下發的業務資料,通過遞歸周遊 WidgetNode Tree 動态生成 Widget Tree,最後顯示上屏。

▐  Flutter-DynamicX元件優化-緩存優化

Flutter 流暢度優化實踐總結

知道了原理,就容易發現上圖紅色框中的流程:二進制(模闆)檔案解析裝載、資料綁定、Widget 動态建立都有一定的開銷。為避免反複開銷,我們對 DxWidgetNode 和 DxWidget 均進行了緩存,藍色選中代碼展示了 Widget 緩存。

▐  Flutter-DynamicX元件優化-獨立 isolate 優化

Flutter 流暢度優化實踐總結

此外,将上述邏輯放置到獨立 isolate 中,最大限度的将開銷降低至最低。經過線上技術灰階 AB 實驗,平均卡頓壞幀比例從 2.21% 降低至 1.79%。

▐  Flutter-DynamicX元件優化-層級優化

Flutter 流暢度優化實踐總結

Flutter DynamicX 提供了類 Android Layout DSL,為實作每個控件 padding、margin、corner 等屬性,增加了 Decoration 層;為實作類 Android FrameLayout、LinearLayout 布局能力,增加了 DXContainerRender 層。每一層都有自己的清晰職責,代碼層次清晰。但也因為增加 2 層導緻 Widget Tree 層級變深,3棵樹的 Diff 邏輯變得複雜,性能變低。為此,我們将 Decoration 層和 DXContainerRender 層進行了合并,檢視中間 Timeline 圖,可以發現優化後的燃焰圖層級和複雜度都變低。經過線上技術灰階 AB 實驗,平均卡頓壞幀比例從 2.11% 降低至 1.93%。

性能衡量和devtool擴充

講述了優化手段,這裡講述我們的流暢度性能如何做衡量,以及工具的建構/擴充。

Flutter 流暢度優化實踐總結

▐  線下場景-flutter benchmark

Flutter 流暢度優化實踐總結
Flutter 流暢度優化實踐總結

檢測 Flutter 每幀耗時,需要統計 UI Thread 和 Raster Thread 上的計算耗時。是以 Flutter 優化前後比較,使用 

SchedulerBinding.instance.addTimingsCallback

 擷取每一幀的 UI Thread 和 Raster Thread 的耗時資料。

此外,流暢度性能數值受操作手勢、滾動速度影響,是以基于人工操作的測量結果會存在誤差。這裡使用 WidgetController 控制清單控件 fling。

工具提供設定滾動速度、滾動次數、滾動之間的間隔時間等。滾動測試完成後,顯示 UI 和 Raster Thread 丢幀數,50分位、90分位、99分位的幀耗時等資料,從多種次元給出了性能資料。

▐  線下場景-基于錄屏的流暢度檢測

Flutter 流暢度優化實踐總結

flutter benchmark 在 flutter 頁面給出了多元度的測量資料,但有時候我們需要橫向比較競品 App,是以我們需要有工具橫向比較不同技術棧的頁面流暢度。閑魚在 Android 端自研了基于錄屏資料的流暢度檢測。将手機界面想象成多個畫面,通過向系統錄屏服務 MediaProjection 注冊擷取 VirtualDisplay,間隔 16.6 ms讀取其中的畫面資料(位元組數組),這裡使用位元組數組的 hash 值代表目前畫面,目前後 2 次讀取的 hash 值不變,則認為發生了卡頓。

為了保證流暢度檢測工具 app自身不發生卡頓,這裡讀取的是壓縮畫面資料,低端機上壓縮比例要更高
Flutter 流暢度優化實踐總結

通過工具無侵入的檢測,可以檢測到一次滾動測試,平均 FPS 值(圖中 57),幀分布均方差(7.28),1s 時間發生的大卡頓次數平均值(0.306),大卡頓累計時間(27.919)。中間數組展示幀分布情況:371 代表正常幀數量,6 代表 16.62ms 的小卡頓數量,1 代表 16.63ms 的卡頓數量。

這裡大卡頓的定義是:大于 16.6*2 ms 的卡頓

▐  線下場景-基于devtool的性能檢測

Flutter 流暢度優化實踐總結

此外,閑魚線下場景也擴充了 devtool。在一次 Timeline 圖擴充了每個階段的耗時,大于 16.6ms 紅色高亮顯示,便捷了開發使用。

▐  線下場景-Flutter高可用檢測FPS實作原理

Flutter 流暢度優化實踐總結

線上上場景,閑魚自研了 Flutter 高可用。基本原理是基于2個事件:

  • ui.window.onBeginFrame 事件
    • engine 通知 Vysnc 信号到來,通知 UI Thread 開始準備下一幀畫面建構  
    • 觸發 SchedulerBinding.handleBeginFrame 回調
  • ui.window.onDrawFrame 事件
    • engine 通知 UI Thread 開始繪制下一幀畫面
    • 觸發SchedulerBinding.handleDrawFrame 回調

這裡我們在 handleBeginFrame 處理之前,記錄一幀開始事件,在 handleDrawFrame 之後記錄一幀的結束。這裡每一幀都需要計算清單控件 offset 值,具體代碼實作見右圖。在整個累計超過 1s 時,執行一次計算,使用 offset 過濾掉沒有發生滾動的場景,使用每一幀的時間計算 fps 值。

▐  線上場景-FlutterBlockCanary線上卡頓堆棧檢測

Flutter 流暢度優化實踐總結

使用 Flutter 高可用計算得到線上 FPS 數值後,如何定位卡頓問題,需要收集堆棧資訊。閑魚使用自研的 FlutterBlockCanary 收集卡頓堆棧。基本原理是,在 C 層輪詢發送信号,比如 5ms 一次,每次信号接收觸發 dart UI Thread 堆棧采集,對得到的一系列堆棧進行聚合,連續多次相同堆棧就認為是發生了卡頓,這時這個堆棧就是我們想要的卡頓堆棧。

上圖是 FlutterBlockCanary 采集的堆棧資訊,中間 FrameFpsRecorder.getScrollOffset 就是發生卡頓的調用。

▐  線上場景-FlutterBlockCanary檢測過度渲染

Flutter 流暢度優化實踐總結

此外,FlutterBlockCanary 也內建了過度渲染檢測的能力。通過複寫 WidgetsFlutterBinding 的 buildOwner 方法替換 BuildOwner 對象,進而重寫 scheduleBuildFor 方法,實作攔截髒 element。基于髒 element 節點,提取出髒節點的深度、直接子節點的數量、全部子節點的數量。

基于全部子節點數量,在閑魚詳情頁,我們定位到“快速提問視圖”在滾動過程中,頻繁被标髒和全部子節點數量過大。檢視代碼,定位該視圖層級過高,通過将視圖下沉到葉子節點,一次标髒 build 節點數量從 255 優化至 43。

Flutter 滑動曲線優化

前面講述了卡頓優化手段和衡量工具和标準,主要還是圍繞着 FPS。但從使用者體感出發,我們發現 Flutter 也有很多可優化點。

Flutter 流暢度優化實踐總結

▐  Flutter 清單滑動曲線和原生曲線

Flutter 流暢度優化實踐總結

分别對比 offset/time 的滾動曲線,可以發現 Flutter BouncingScrollSimulation 和iOS 滾動曲線接近,ClampingScrollSimulation 和 RecyclerView 接近。檢視 Flutter 源碼注釋,也确實是如此。

因為 BouncingScrollSimulation 具有回彈能力,是以很多下拉重新整理和加載更多功能,都是基于 BouncingScrollSimulation 封裝實作,這也就造成 Flutter 頁面滑動時,體感和原生 Android 頁面不一緻的原因。

▐  Flutter 清單在快速滑動下的表現和優化

Flutter 流暢度優化實踐總結

雖然 ClampingScrollSimulation 滑動曲線和 Android RecyclerView 接近,但在快速滑動場景下,可以發現 Flutter 清單滾動快停止的時候會像磁鐵吸住一般,快速滑動一下停止。究其原因,可以看到滑動曲線快停止的瞬間,速度并不是下降,而會加快,最後到達終點,快速停止。基于源碼公式,繪制曲線,可以發現,Flutter ClampingScrollSimulation 是通過公式拟合方式,去逼近 Android RecyclerView 曲線(BSpline)。在快速滑動的情況下,公式曲線的重點并不是 1 對應的值,而是右圖虛線位置,速度會變快。

可以了解 Flutter 的公式拟合結果并不理想,為此近期也有 PR 提出使用 dart 實作了 RecyclerView 曲線。

▐  Flutter 清單在卡頓情況下的表現和優化

Flutter 流暢度優化實踐總結

第一章提過相同 FPS 情況下,如 FPS 55,原生清單感受流暢,而 Flutter 清單的卡頓體感更明顯。這裡一個原因是原生清單通常有多線程操作,出現大卡頓的機率更低;另一個原因是,相同小卡頓的體感,Flutter 有明顯的卡頓感,而原生清單幾乎感受不出來。那這是為什麼呢?

我們在建構卡片的時候,故意制造小卡頓,在前後對比 Flutter 清單和 RecyclerView,可以發現 RecyclerView offset 并不會發生跳變,而 Flutter 曲線有很多毛刺,因為 Flutter 滾動是基于 d/t 曲線計算,當發生卡頓的時候,△t 發生翻倍,offset 也發生跳變。也正是因為時間停頓和 Offset 跳變,讓使用者明顯感受到 Flutter 清單在小卡頓的不流暢感。

Flutter 流暢度優化實踐總結

通過修改 y=d(t) 公式,在卡頓情況下,将△t-16.6ms,保證小卡頓情況下,offset 不發生跳變。而在大卡頓情況下,就沒有必要将 △t 重置為 16.6ms 了,因為在停頓時長上,已經明顯讓使用者給感受到卡頓了,offset 不發生跳變隻會讓清單滾動距離變短。

性能優化建議

Flutter 流暢度優化實踐總結
Flutter 流暢度優化實踐總結

最後分享一些性能優化的建議。

  1. 在優化時,我們更應該關注使用者體感,而不是隻看性能數值。右上圖可見,即便 FPS 值一樣,但 offset 發生跳變,體感就會有明顯的不同;右下2個遊戲錄屏,左邊平均 40 FPS,右邊平均 30 FPS,但體感上卻是右邊的更順暢。
  2. 不僅要關注 UI Thread 的性能,也要關注 Raster Thread 的開銷,如視圖圓角、save layer 等特性/操作,也可能導緻卡頓
  3. 在工具方面,建議在不同場景下使用不同的工具。需要注意的是,工具檢測的問題,是穩定複現問題還是資料抖動産生的偶現問題。此外,也要考慮工具自身的性能開銷,工具自身的 CPU 占用和主線程占用都需要盡可能降低。
  4. 在優化思路方面,我們要擴寬方向,Flutter 大部分優化思路都是優化計算任務;而多線程方向也并不是不可以,參考前面 Flutter DynamicX 的獨立 isolate 優化;此外,一幀時間難以消化的任務,是否有可能拆解到多個幀時間,盡量讓每幀時間不發生卡頓,優先響應使用者。
  5. 最後,推薦關注 Flutter 社群。Flutter 社群持續有各種優化合入,定期更新 Flutter 或次元自己的版本,cherry-pick 優化送出,都是不錯的選擇。

▐  性能分析工具使用建議

Flutter 流暢度優化實踐總結

Flutter 工具方面,首推的就是官方的 DevTools 工具,裡面的 Timeline 和 CPU 燃焰圖能很好的協助我們發現問題;此外,Flutter 也提供了豐富的 Debug Flags 協助我們定位問題,熟悉每一個 debug 開關作用,相信對我們日常研發也會有不小的幫助;除了官方工具,性能日志也是很好的輔助資訊,如右下角所示,閑魚 fish-redux 元件輸出了滾動中的任務開銷時長,能友善的看出那一時刻發生了卡頓。

▐  性能分析工具自身開銷

Flutter 流暢度優化實踐總結

性能檢測工具不可避免會有一定的開銷,但一定要控制在可接受範圍内,特别是線上使用。前面分享過 FlutterBlockCanary 檢測工具的一個案例,發現了 FrameFpsRecorder.getScrollOffset 有耗時情況,而這處邏輯正好是 Flutter 高可用計算滾動 Offset。見右圖的優化前源碼,每一幀都需要遞歸周遊收集 RenderViewPortBase,是一個不小的開銷。最後,我們通過緩存優化的方式,避免了滾動過程中的反複計算。

▐  卡頓優化建議

Flutter 流暢度優化實踐總結

參考官方文檔和優秀的性能文章,在 UI 和 GPU 側都沉澱了很多正常優化手段,如重新整理最小 Widget,使用 itemExtent,推薦使用 Selector 和 Consumer 等,避免了不必要的 Diff 計算、布局計算等;如減少 saveLayer、使用圖檔替換半透明效果等減輕了 Raster 線程的開銷。

因為篇幅原因,這裡隻列了一部分,更多的常見優化建議見官方文檔。

▐  使用最新 flutter engine

Flutter 流暢度優化實踐總結

前面提過,Flutter 社群還在活躍,Framework 和 Engine 層持續的有優化 PR 合入,這些優化手段大部分可以讓業務層無感覺,并且從底層視角更好的優化性能。

這裡舉一個典型的優化方案:現有 Flutter 方案:在每次 VSync 信号到來時,觸發 Build 操作,在 Build 結束時,開始注冊下一個 VSync 回調。在沒有發生卡頓的情況下,見圖 Normal。但在發生卡頓的情況下,見圖 Actual results,這裡

2 Build

耗時剛剛超過了 16.6ms,由于是注冊監聽下一個 VSync 回調時觸發下一次 Build,為此中間空餘了大量的時間。明顯,我們所期望的是,

2 Build

結束時,立即執行

3 Build

,假設

3 Build

執行的足夠快,這個時候使用者看到的畫面還是流暢的。

如果團隊允許,建議定期更新 Flutter 版本;或者維護自己的 Flutter 獨立分支也是不錯的選擇,從社群 Cherry-Pick 優化送出,既能保證業務穩定也能享受社群貢獻。總之,推薦大家關注社群。

總結

綜上,分享了 Flutter 流暢度優化的挑戰、監控工具、優化手段和建議。性能優化要以人為中心,從實際體感入手制定監控名額和優化點;流暢度優化并不是一蹴而就,以上分享也不是全部,還有很多優化手段可以關注:如何更好的複用 Element,如何避免 Platform Thread 繁忙導緻 Vsync 信号缺失等都是可以關注的點,隻有持續的技術熱情和匠心精神才能把 App 性能優化到極緻;技術團隊也要和開源社群、其他團隊/公司建立連接配接,他山之石,可以攻玉。

團隊介紹

閑魚技術用戶端團隊和 Google Flutter 團隊密切合作,在端技術和跨端方案上持續深耕,為社群貢獻多個高 star 的項目和大量 PR。閑魚 APP 是中國最大的閑置交易平台,是阿裡巴巴正在催生的第三個萬億級平台,擁有極大的創新空間和可能性。有意願加入我們團隊的,歡迎來撩,郵箱:[email protected](發送郵件時,請把#替換成@)

繼續閱讀