Flutter 耗時監控 | 路由名為空原因分析

碼裡特別有禪發表於2023-01-27

前言

最近群裡遇到獲取Route名為空的問題,當時沒在意。。。

Untitled.png

直到自己在監控頁面啟動耗時,需要確定當前頁面是哪個從而方便標記它載入的耗時時,遇到同樣 route.settings.name 為空問題,模擬場景如下:

  1. 在 main.dart 頁面中點選 + 按鈕跳轉到 TestPage2 頁面。
  2. MaterialApp 中設定路由守衛並在路由守衛中列印 route 名。

Untitled 1.png
main.dart

Untitled 2.png
launch_observer.dart

Untitled 3.png
TestPage2.dart

路由守衛中列印結果如下:

Untitled 4.png

可以看出

  • 應用啟動進入 main 列印是正確的,之前沒有頁面,進入時候列印 route = /
  • 進入 TestPage2 時,previewousRoute 的 name = / 正確,但是當前 route 的 settings.name 卻為 null ,這就比較奇怪了。

我試著復現文章開頭的例子,程式碼如下:

  1. main.dart 不變,點選 + 跳轉到 TestPage2
  2. 在 TestPage2 中獲取路由引數和路由名字

Untitled 5.png

結果發現:name 的值仍然為 null;

Untitled 6.png

## 問題分析

MaterialPageRoute 繼承關係

Untitled 7.png

最終我們要得到的 name 其實是 Route 內部的 RouteSettings 物件的 name。

Untitled 8.png

而透過繼承關係追溯,最終 Route 中的 RouteSettings② 由 MaterialPageRoute① 傳過來。

Untitled 9.png

Untitled 10.png

解決辦法

很簡單,在跳轉頁面之前給 MaterialPageRoute 設定 settings 屬性。

Untitled 11.png

這樣就可以接受到 name 和傳遞過去引數了,如圖:

Untitled 12.png

能不能自動設定 RouteSettings

答案: 拿不到。

思路一:

有這個想法是因為涉及到老程式碼的遷移,很多老程式碼不想一個個改加 Settings,偷個懶。而且平時用的時候大部分情況下都不會帶 settings 屬性。

當然跟我有同樣想法的人也有 flutter - How to get the Widget Class name from the builder object in MaterialPageRoute - Stack Overflow

Untitled.jpeg

嘗試如下:

Untitled 13.png

PS: 哪位大佬有更好解決自動新增 RouteSetting 屬性辦法希望不吝賜教,多謝。

換個思路

群裡大佬指出可以嘗試換個思路: aop buildpage。這裡找到個帖子是這種思路,沒驗證各位大大可自行辨別,哈哈。

Flutter aspectd(五)全域性監控 flutter 生命週期

核心點

當我們要開啟一個新的 flutter 頁面會執行 Navigator.pushNamed(context, RouteHelper.firstPage),最終會執行 navigator.dart 中的 handlePush 方法,hook 該方法,從該方法中可以得到我們要啟動頁面的 Route,以及當前的頁面 Route。

Untitled 14.png

總結

  1. Route.settings.name 無法獲取原因是 push/pushNamed 時 MaterialPageRoute 沒設定 RouteSettings 屬性。
  2. 如果老專案有埋點等需求需要監控頁面名,建議老老實實給每個 MaterialPageRoute 加 RouteSettings 屬性比較穩妥。
  3. 最最推薦的做法是透過 APT 方式模組化路由功能,這樣應用中所有 MaterialPageRoute 生成過程就可以收攏,生成程式碼時將 RouteSettings 屬性新增上即可。

如果覺得文章對你有幫助,點贊、收藏、關注、評論,一鍵四連支援,你的支援就是我創作最大的動力。

❤️ 本文原創聽蟬 公眾號:碼裡特別有禪 歡迎關注原創技術文章第一時間推送 ❤️

PS: 文中所有原始碼獲取方式:公眾號後臺回覆 “route”

參考連結

flutter - How to get the Widget Class name from the builder object in MaterialPageRoute - Stack Overflow
Flutter aspectd(五)全域性監控flutter生命週期 - 掘金

相關文章