作者:閑魚技術-雲從
1 整體思路
閑魚在業務的快速疊代過程中,app 的長清單滑動流暢度逐漸惡化,對使用者浏覽内容體驗産生傷害。閑魚作為國内 flutter 應用的先驅,APP 以 flutter 和原生 Native 的混合工程存在。這裡分别就 Android 原生、flutter 頁面和大家分享我們的優化思路。
本文分為三個部分:
- 流暢度名額和檢測工具建構
- 原生 Android 長清單優化
- flutter 長清單優化
流暢度優化整體思路圖如下:

2 流暢度名額和檢測工具建構
2.1 現狀和難點
檢測工具現狀:以 Android 為例,現有流暢度工具可分為:
- 侵入式
- 內建 sdk,通過注冊幀回調計算流暢度。Android 見 Choreographer 類
- profile 模式
- 無侵入式
- 執行系統指令,如
adb shell dumpsys gfxinfo ${packageName}
- 騰訊 GT APP,底層執行
,高版本 Android 已不支援service call SurfaceFlinger 1013
- 執行系統指令,如
流暢度名額現狀有:
- FPS (Frames Per Second)
- SF(SkippedFrame,跳幀)
- 在機關時間 1 秒内,跳過執行 Choreographer 中 doFrame() 的次數 (見 《移動App性能評測與優化》 )
- SM(Smooth,流暢度)
-
幀耗時資料
使用 adb 指令得到幾個關鍵分位的幀平均耗時:
Total frames rendered: 2245
Janky frames: 31 (1.38%)
50th percentile: 5ms
90th percentile: 10ms
95th percentile: 14ms
99th percentile: 18ms
然而以上工具和名額定義在 app 的複雜場景下,尚存在問題
-
多平台問題
現 APP 技術有原生、h5、小程式、RN、weex、flutter 等。暫無一款無侵入的流暢度檢測工具能同時支援多個平台、多種機型和多個名額資料,而侵入式的檢測工具無法檢測競品 APP。
-
名額選擇和使用者體驗一緻性
我們期望能有少量的幾個名額資料,準确的表達使用者流暢度體感。
平均 FPS(SM 和 SF 類似),不足以反映使用者體驗。如相同 30 FPS,可以是 1s 内 30 個 33.3 ms的畫面,也可以是 29 個 16.6ms 的畫面再加 1 個 516.9 ms 的畫面,但使用者體驗并不相同。
-
流暢度資料影響因素多
滑動速度和滑動狀态:idle(停止)、drag(手指拖拽)、fling(自由滑動)都是影響流暢度資料的重要因素。
2.2 流暢度名額制定
維基百科動畫定義:一種通過定時拍攝一系列多個靜止的固态圖像(幀)以一定頻率連續變化、運動(播放)的速度(如每秒16張)而導緻肉眼的視覺殘象産生的錯覺——而誤以為圖畫或物體(畫面)活動的作品及其影片技術。
清單滑動同理,是 APP 以一定頻率(60hz下16.6ms)和不同 offset 計算出一系列靜止畫面,讓肉眼看到滑動動畫。
當我們說清單滑動不流暢,是因為頻率過低無法讓肉眼産生視覺殘留,或在時間(畫面停留時長)和空間(畫面内容)産生跳變,讓使用者感覺到變化的不自然。以此我們可以定義名額如下:
- 時間角度
- 定義平均 FPS:定義一次檢測的平均幀率。反應畫面平均停留時長。
- 定義 1s 大卡頓次數:平均 1s 内出現占用 3 幀及以上的畫面次數。反應畫面停留時長跳變
- 空間角度
- offset 跳變值:在畫面不掉幀的情況,若其中一個畫面出現跳變,甚至花屏或者綠屏會讓使用者體驗到不流暢。在 APP 滑動過程中,畫面内容由 offset 決定,而 offset 跳變,和卡頓時長、內插補點器實作均有關聯,現有內插補點器實作基本基于 D/T 曲線(距離/時間),為此平均 FPS 和 1s 大卡頓次數很大程度上展現了畫面跳變,同時考慮到無侵入式檢測 offset 的難度問題,暫不考慮 offset 跳變值。
綜上,我們定義流暢度名額為平均 FPS 值和 1s 大卡頓次數。
2.3 流暢度檢測工具實作
我們從 APP 錄屏畫面入手,計算流暢度名額值。當我們得到 APP 滑動過程中的錄屏資料,可通過每 16.6ms 檢測錄屏畫面是否發生變化,當連續畫面未發生變化,則表示發生了卡頓。無變化的連續畫面數則表示了卡頓的時長。

為得到目标 APP 錄屏資料,檢測工具 APP 向系統注冊錄屏服務,然後在檢測工具 APP 的幀回調中不停讀取錄屏畫面,并和上次檢測畫面 hash 值進行比對。
- 檢測工具 APP 和目标 APP 程序隔離,為此目标 APP 發生卡頓并不影響檢測工具 APP 的幀回調
- 為保證每次錄屏畫面讀取和 hash 值計算在 16.6ms 内完成,需根據高低端機型調整畫面寬高壓縮比。

為排除滑動操作對流暢度數值的幹擾,我們使用腳本操作檢測工具 APP 和目标 APP 的滑動。自動化腳本原理為使用 adb 指令操作手機
點選:adb shell input tap $x $y
滑動:adb shell input swipe $x1 $y1 $x2 $y2 $duration
2.4 檢測工具示範
流暢度檢測工具 APP 以懸浮框的方式顯示,下面為目标檢測 APP:
流暢度檢測工具界面
2.5 小結和展望
在流暢度名額方面,我們定義了平均 FPS 和 1s 大卡頓次數作為名額,更好的反應了使用者體驗。
在流暢度檢測工具方面,我們實作了無侵入檢測工具,支援以下特性:
- 無侵入
- 支援檢測第三方 app
- 支援多平台:native,flutter,h5,小程式
- 多元度資料:平均 FPS,平均 1s 大卡幀次數,幀分布直方圖,幀分布均方差
- 自動操作,避免人為操作差異
此外,流暢度檢測工具還有一些不足之處
- 清單中有視訊卡片
- 停止滑動時,若清單中有視訊播放,由于畫面一直在變化,檢測工具無法判斷是滑動停止;同時,由于視訊 fps 值為 30 左右,會導緻流暢度資料偏低
- 如何避免:檢測過程中,需保證清單滑動不停止
- 低端機(y67)真實 fps 計算存在偏差
- 為保證低端機上(如 vivo y67)上計算大圖像 hash 值在 16ms 以内,錄屏畫面壓縮較大(寬度壓縮 100,高度壓縮 10),為此在大量空白或者大色塊的場景下,無法檢測到畫面的細微變化,fps 計算存在偏低。
- 如何避免:避免低端機上檢測大量空白或大色塊的場景
3 原生 Android 長清單優化
Android 原生長清單優化已經非常成熟了,在工具方面有 traceview、blockcanary、DDMS、Android Profile 等。常見優化手段也很多:布局層級優化,過度渲染優化,頻繁measure、layout優化,UI 線程耗時方法優化、備援資源資源加載優化等,這裡不再贅述。
除此之外閑魚使用以下 2 點優化首頁
3.1 異步建構視圖緩存池
通過工具檢測或耗時列印,發現清單初始滑動和 loadmore 時觸發 item 視圖建構耗時嚴重(RecyclerView.onCreateViewHolder)

檢視首頁顯示和初始滑動流程,可以發現流程中其他 UI 操作過程和等待使用者操作過程均有優化空間。

利用 AsyncLayoutInflater 原理異步建構視圖緩存池,優化首頁清單流程如下:

其中視圖緩存池建構完成的時機在不同機型下不同,可能在清單首屏多卡片建構之前,或建構中,或在使用者滑動操作之前完成,或一開始建構就抛出錯誤停止建構
注意:不能直接使用 AsyncLayoutInflater,AsyncLayoutInflater 在異步建構失敗後有一個降級到 UI 線程建構的邏輯,為避免降級邏輯發生導緻緩存池在 UI 線程建構,導緻頁面更加卡頓,需要移除這個降級邏輯:出現異步 inflater 失敗,停止緩存池建構。
3.2 ViewDataUnbinder 快速抽離 UI 操作
在卡片資料綁定階段(RecyclerView.onBindViewHolder),在低端機上耗時較為嚴重,原因是在卡片資料綁定方法中,而 UI 和非 UI 操作糅合在一起,由于 UI 邏輯必須在 UI 線程執行,最終導緻全部邏輯隻能在 UI 線程執行。
能想到定義視圖資料層,将 UI 和非 UI 操作分離開,然而實際編碼發現業務代碼改動量大且容易出錯,AB 測試邏輯難以實作。那有沒有更好的方案,用最少量代碼抽離 UI 操作呢?

核心思路:編譯期根據視圖類自動生成 ViewData 類,并替換視圖類執行個體。ViewData 類和視圖類擁有相同的關鍵方法簽名,方法執行時記錄視圖操作,統一切換到 UI 線程執行視圖操作。

具體使用代碼樣例如下
-
注解視圖類
使用 ViewDataAnno 注解視圖類,UIMethodAnno 注解 UI 操作方法。

其中注解說明

- 生成 ViewData 類

- 業務代碼修改
- 修改視圖變量為 ViewData 類型
- 原視圖資料綁定邏輯放置背景線程
3.3 優化結果

閑魚首頁,在恢複内容上屏速度(流暢度降低)後提升流暢度
4 Flutter 複雜長清單優化
flutter 一直以高性能被大家所認知,參考
Flutter 是如何做到性能直逼 native 的?,這也是閑魚當初選擇 flutter 的一個重要原因。而在閑魚的實際 flutter 頁面,如商品詳情頁和搜尋結果頁,長清單滑動流暢度體驗卻不盡人意。
4.1 工具使用和常見優化
做性能優化前,需要了解 flutter 的渲染原理,如 Widget、Element、RenderObject 三棵樹結構、Widget 到螢幕顯示過程等,可參考
超詳解析Flutter渲染引擎,
複雜業務如何保證Flutter的高性能高流暢度?。
針對性能問題,首推官方性能分析工具并結合使用 profile 模式檢視性能問題,參考
Flutter Performance 分析工具簡介Profile 模式隻能在真機上運作,不能在模拟器上運作:基本和 Release 模式一緻,除了啟用了服務擴充和 tracing,以及一些為了最低限度支援 tracing 運作的東西(比如可以連接配接 observatory 到程序)。指令 flutter run --profile 就是以這種模式運作的,通過 sky/tools/gn --android --runtime-mode=profile 或者 sky/tools/gn --ios --runtime-mode=profile 來 build。因為模拟器不能代表真實場景,是以不能在模拟器上運作
引自:
Flutter性能調優、複雜業務保證Flutter的高性能高流暢
4.1.1 檢查 widget rebuild 情況
Android Studio 上
View
→
Tool Windows
Flutter Performance
打開檢測 Widget rebuild 情況,可以發現 FDButtonBar 被頻繁重建,然而檢視視圖内容并沒有發生變化。檢視代碼定位到
reducer.dart
中會根據滑動事件更新 state 中的
scrollPercent
,進而産生重建。而在詳情頁中,
scrollPercent
在 Widget 建構中并未參與使用。
閑魚頁面中使用了 fish-redux,在 reducer.dart 的方法中傳回不同的 state 對象則表示需要重建 widget
// reducer.dart
// 滑動事件監聽
static BottomBarState onScroll(BottomBarState state, Action action) {
...
return state.clone()..scrollPercent = scrollPercent;
...
}

4.1.2 使用 fish-redux 性能日志
fish-redux是閑魚研發一套在 flutter 上的 redux 架構,閑魚 APP 中有廣泛應用。fish-redux 中自帶性能日志,源碼檢視
performance.dart,若需要列印 profile 或 release 模式下的性能日志,可自行修改源碼。
閑魚詳情頁滑動時,檢視 adb 日志,可以發現大量的滑動廣播通知,且存在耗時 1ms 以上事件處理。
11-15 15:03:43.684 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 261
11-15 15:03:43.701 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 1933
11-15 15:03:43.716 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 371
profile 模式下時間日志

因為詳情頁中存在視圖間關聯,如标題欄的顯示隐藏漸變,
問賣家
的顯示消失均需要根據滑動事件做判斷。結合業務邏輯,可以發現,除了
問賣家
外,其他視圖在滑動超出 600 之後,收到滑動事件後不會發生視圖内容變化;而
問賣家
在滑動超出更大的一個值後會永遠消失不顯示,在一開始未超出這個值時,僅需要判斷滑動方向即可。基于以上業務背景,在滑動超出 600 後,若
問賣家
是不再顯示狀态,則不發送滑動事件;否則僅在開始滑動的 30 距離内發送事件。
此外,可以利用 fish-redux 的特性:若 reducer.dart 中傳回新的 state 對象則表示 widget 重建,檢查全部的 reducer.dart 檔案内方法實作,排查可能發生的無效 widget 重建。
4.1.3 優化 ClipPath 和 ClipRPath
使用 Timeline 檢視渲染線程性能消耗,可以發現有多個
ClipRectLayer
和
ClipRRectLayer


打開 Debug flag
debugDisableClipLayers
debugDisablePhysicalShapeLayers
重新檢查視圖,可以發現部分 ClipRectLayer 是因為圖檔内容超出視圖邊界産生,部分 ClipRRectLayer 是因為卡片 Widget 圓角設定以及基于外接紋理的圖檔控件裡設定了 ClipRRect 設定(即便 radius 為0也會設定)
了解原理後,我們對閑魚圖檔控件新增參數,支援圖檔内容圓角設定和圖檔内容寬高裁剪,使 native 層生成的 Bitmap 已經滿足圓角和寬高比要求。同時修複 radius 為0也會設定 ClipRRect 的問題。優化後的 Timeline 圖如下:

4.1.4 其他優化建議
flutter 性能優化相關的優秀文章很多,本文不再對類似的排查和優化手段做贅述,這裡做下簡單彙總:
- widget build 優化
- setState 狀态重新整理位置盡量放置于視圖樹的低層級
- Provider 中擷取 Model 的方式會影響重新整理範圍。推薦使用 Selector 或 Consumer 來擷取祖先 Model,以維持最小重新整理範圍
- 對于長清單,避免使用 ListView() 構造函數,推薦使用 ListView.builder 構造函數
- reducer 中,state 對象中的視圖資料真正發生變化的時候,建立 state 對象
- 主 isolate 優化
- 減少或延遲 widget build 中非視圖邏輯,如曝光埋點延遲到滑動停止聚合觸發
- 清單 Item 高度可知的情況下,推薦設定 itemExtent,減少滑動中頻繁計算清單高度
- 使用 const 修飾無需變更的 widget 或普通對象
- 使用 AnimatedBuilder 時,避免在不依賴于動畫的 widget 的構造方法中建構 widget 樹。動畫的每次變動都會重建這個 widget 樹。而應該建構子樹的那一部分,并将其作為 child 傳遞給 AnimatedBuilder
- 避免在動畫中剪裁。如果可能,請在動畫開始之前預先剪切圖像
- Render 線程優化
- 對于頻繁更新的控件(如動畫),使用 RepaintBoundary 隔離它,建立單獨 layer 減少重繪區域
- 使用圖檔替換半透明效果
- 減少 saveLayer(ShaderMask、ColorFilter、Text Overflow)、clipPath的使用,提升 render 線程性能
- 避免使用 Opacity widget,尤其是在動畫中避免使用。請用 AnimatedOpacity 或 FadeInImage 進行代替
- 避免使用帶換行符的長文本
- 工具推薦
4.2 清單 element 複用優化
flutter 清單控件劃分為可視區域和 Cache 區域,往下滑動時 element 從底部被建立進入底部 Cache 區域後,再進入可視區域,再進去頂部 Cache 區域,最後被銷毀。往上滑動邏輯類似。在不使用 keepAlive 的情況下,來回滑動,曾經建立過的 element 需要重新建立。而在我們的業務中,清單 item Widget 結構是接近的,此時如果能根據類型複用 element,就能一定程度的提升性能。
清單控件源碼見 sliver_list.dart 中 RenderSliverList.performLayout()
element 緩存在 _childElements 數組中,以 index 為索引。源碼見 sliver.dart
若 item Widget 結構差異很大,即便複用了 element,Element.updateChild 方法内部最終還是執行了 inflateWidget 方法,對于性能提升就沒什麼價值了

我們建構
index
${widget.key}
List<element>
的映射關系:在 widget 建立處建立
index
${widget.key}
映射,在 element 應該被銷毀移除的邏輯處,将 element 緩存至
${widget.key}
映射的
List<element>
處(注意 renderObject 對象需要從父節點移除)。清單滑動過程中,優先根據映射關系找到緩存中的 element 并使用(注意更新 element.renderObject.parentData 中的 index 值)
4.3 複雜 Widget 分幀上屏
以上全部優化手段嘗試後,在閑魚的詳情頁和搜尋頁上還是遠沒有達到預期。原因是猜你喜歡卡片和搜尋頁卡片本身就足夠複雜,另外由于我們引入 DX 技術讓 Widget 進一步變得巨大,最終導緻的結果是:即便高端機,也無法在一幀時間内完成渲染。
然而抛開技術視角,從業務視角看,卡片展現内容和 DX 的動态能力都是必需的。那如何在滿足業務訴求的情況下,實作超大 Widget 的高性能呢?

業務側僅需 Text,但在 DX 技術中使用的是 DXTextWidget

猜你喜歡卡片在 紅米 K30Pro(CPU 骁龍 865)的 Timeline 圖

搜尋結果卡片 Timeline 圖,補充了 performLayout、updateChild、Widget build
在已知常見優化手段無法滿足的情況下,我們回歸 GUI 系統性能優化的起點去思考問題。流暢度優化思路,大體可以分為 3 個方向:
-
多線程方案
在 Android 原生開發中很常見。但在 dart 世界中,不同線程(isolate)的記憶體是隔離的,此外由于 flutter 渲染流程三棵樹,我們不好直接操作 RenderObject,多線程方案在 flutter 中較難實施(排除 IO 更新資料後顯示等正常場景)
- 優化每個任務,擠壓 CPU 運算量,保證一幀時間(16.6 ms)完成任務
- 中的主流優化思路,前面的優化手段都是這個思路
-
快速響應使用者,讓使用者覺得夠快,不阻塞使用者的互動。即一幀時間内還有任務沒有完成,則停止執行,保證清單先執行滑動,未執行任務在後續幀時間片上執行
參考 React Fiber 架構,基于時間分片的思路,協調階段将一顆任務樹轉為一條任務鍊(parent 節點 → child 節點 → sibling 節點 → parent 節點),滿足了任務鍊可中斷執行,提前送出渲染,最後實作了将一條任務鍊拆解到多幀時間分片中消化。

排除方向 1、2 後,隻剩下方向 3。再結合猜你喜歡卡片 Timeline 圖可以發現,在卡片 Widget 建立的一幀發生時間不足,而後面的幾幀内時間消耗都遠沒到 16.6 ms,可以想到方向 3 是正确的。那剩下的關鍵問題僅有以下 2 點:
- 能否将一個大 Widget build 任務為拆分多個小 Widget build 任務并大緻平均的配置設定到多個時間分片上?
- 一個大 widget 分時間片上屏是否會影響體驗?

Timeline 上任務耗時圖
Flutter widget 拆分和分幀上屏
基于時間分片的大方向,我們把一個大 widget 拆分為一個空白架構和 2 個卡片 widget,再将卡片 widget 拆分為一個卡片架構和多個 FXImage Widget,Widget 架構中不立馬顯示的部分使用占位 Widget 臨時代替。
由此建構一個高優大任務隊列和一個低優小任務隊列,高優大任務隊列中的任務高優執行且獨占一幀時間,低優小任務隊列低優執行且一幀時間最多能執行 12 個任務。再利用 flutter 逐漸标髒,将 build 任務延遲到後續時間分片上。

以上最終将一個超大 widget 建構從 1 幀時間分散到 4 幀時間内消化,優化了卡頓。

優化後猜你喜歡卡片 Timeline 圖(紅米 K30Pro,CPU 骁龍 865)
在體驗方面,前面講清單控件結構時已知有一個不可見的 Cache 區域,是以分幀上屏大部分是在這個不可見區域完成的,為此在高端機或正常滑動情況下使用者并無感覺。而在低端機上快速滑動能明顯看到卡片空白情況,但整體相比嚴重頓挫體感要好。
4.4 優化資料
基于上面的優化手段,閑魚詳情頁和搜尋頁流暢度 FPS 提升了 3 個點,低端機大卡頓次數降低一半,中高端機型上流暢度提升到 57 或以上,大卡頓次數接近 0。
詳情頁
線上高可用 fps 資料如下:

線上低端機 fps 曲線。綠色為優化版本
曲線分布越靠右,流暢度越好

線上高端機 fps 曲線。綠色為優化版本
搜尋頁


4.5 滑動內插補點器優化
完成上面優化後,線下自建流暢度檢測工具資料和線上 fps 資料曲線都有很大的提升,且資料名額接近原生 APP 流暢度。在中高端機型上,閑魚詳情頁 FPS 已經被我們優化到了 57 及以上了,1s 大卡頓次數接近 0。在原生 APP 流暢度 FPS 數值達到 57 及以上時,滑動過程中基本上不會感受到卡頓,然而,flutter 頁面的實際滑動操作中,還是能感受到卡頓。
回顧自建流暢度檢測工具原理:基于每幀畫面比對、無侵入,相同的自動化腳本,是以相信我們線下測試的資料(平均 FPS 和 1s 大卡頓次數)是準确的。性能資料接近,而體感有差異,且性能資料準确可信,是以可以确認流暢度名額(平均 FPS 和 1s 大卡頓次數)還不能完全反應體感。
再回顧 2.2 流暢度名額制定,可以發現我們并沒有對空間次元的 offset 跳變(畫面内容跳變)做檢測。基于此,我們可以對比 Android 原生 RecyclerView 和 Flutter SliverList 在卡頓情況下 offset 變化情況

Android 原生 RecyclerView 和 Flutter SliverList fling 階段 offset/time 曲線圖
由上可以得到,同樣在 FPS 值達到 57,Android RecyclerView 在使用者體感上比 flutter 清單控件更好的原因:在小卡頓時,offset 偏移值并沒有發生翻倍跳變。
檢視 flutter 滑動算法,可以發現是基于一條 D/T 曲線計算滑動距離,是以發生卡頓時,輸入 timeOffset 值發生翻倍,最終計算出來的 offset 值發生近乎翻倍。

flutter ClampingScrollSimulation D/T 曲線
為消除在發生小卡頓時,offset 跳變的情況,我們自定義了 physics 和 simulation,在 time 發生發生小跳變時,修改滑動距離算法,采用 V/T 曲線算法,distance 通過累加的方式計算,優化了 time offset 發生翻倍而導緻曲線跳變的情況
distance = velocity(time) * 16.6ms + distance
注意:需要适配系統頻率大于 60 hz 的機型(如 90hz,120hz),在一幀時間内有可能計算多次 distance
以 V/T 曲線為基礎,我們提供了以下滑動內插補點器:
-
SmoothClampingScrollPhysics
無回彈內插補點器,停頓後偏移值不跳變。 結束滑動的效果同 ClampingScrollSimulation

-
SmoothBouncingScrollPhysics
回彈內插補點器,停頓後偏移值不跳變

5 總結和展望
經過上述優化,在原生 Android 方面,閑魚首頁流暢度和内容上屏得到明顯提升;在 Flutter 方面,閑魚詳情頁和搜尋頁流暢度 FPS 提升了 3 個點,低端機大卡頓次數降低一半,中高端機型上流暢度提升到 57 或以上,大卡頓次數接近 0,相同小卡頓在體驗上得到了提升。
流暢度優化是每一個 GUI 系統都一直在努力的事情,有很多優秀的工具介紹、官方和非官方的優化文章。這次優化過程中,我們也借鑒了很多别人的文章,發現和優化了一些問題,但本文盡量不去重複描述,推薦讀者閱讀相關優化文章或官方文檔。
在以上優化手段尚無法實作最終目标時,我們也做了一些不一樣的優化,期望能抛磚引玉,對讀者有所幫助和啟發:
- 基于使用者體驗為導向建構了流暢度名額:平均 FPS,1s 大卡頓次數
- 針對名額,自建了流暢度檢測工具,支援無侵入、跨平台、自動化
- [Android] 顯示 ViewDataUnbinder 元件在複雜業務邏輯中快速抽離 UI 操作
- [Flutter] 修改 Flutter engine 源碼,支援清單 element 複用
- [Flutter] 實作大 Widget 分幀上屏元件
- [Flutter] 內插補點器算法優化
後續我們會繼續思考以下内容:
- 如何将流暢度檢測工具内部産品化,支援非研發同僚使用?
- 如何使用已有的經驗、工具、元件快速優化其他業務頁面?
- 如何在研發階段及時發現和防止無效 rebuild 等問題?
- 如何在 CI 平台及時發現頁面流暢度惡化情況?
- 如何以業務無侵入的方式實作業務大 Widget 自動且合理地分幀上屏?