Route transition record 和 transition delegate 更新
關於 transition delegate 如何解析路由轉場的規則變更。
摘要
#
在 route transition record 中新增了一個布林值 getter isWaitingForExitingDecision,
並且將 isEntering getter 改名為 isWaitingForEnteringDecision。
在 transition delegate 的 resolve() 方法中,
請使用 isWaitingForExitingDecision 來檢查一個即將離開的 Route
是否真的需要明確決定如何從螢幕上移除。
如果你嘗試對一個「不需要等待決策」的既有 Route 做出決策,
Flutter 會拋出 assertion error(斷言錯誤)。
背景說明
#
當 Navigator 收到新的 pages 清單時,會嘗試將目前的 routes stack
同步至該清單。不過,這需要明確決定每個 Route 要如何進入或離開螢幕。
過去,所有不在新清單中的 Route 都需要決定如何離開螢幕。
但後來發現,這並不總是正確。如果某個 Route 已被 pop,
但仍在等待 pop 動畫結束,
這個 Route 會暫時留在 Navigator 的 routes stack 直到動畫完成。
如果這段期間發生了 page 更新,
這個 Route 會離開,但不需要決定如何從螢幕上移除。
因此,新增了 isWaitingForExitingDecision 來涵蓋這種情境。
同時,isEntering getter 也被重新命名為
isWaitingForEnteringDecision,讓名稱更具描述性且更一致。
遷移指南
#
如果你有自訂 transition delegate,
在呼叫 markForPop、markForComplete 或 markForRemove
之前,
需要先用 getter isWaitingForExitingDecision 檢查即將離開的 Route。
另外,也需要將所有 isEntering 的參考名稱改為
isWaitingForEnteringDecision。
遷移前的程式碼:
import 'package:flutter/widgets.dart';
class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
@override
Iterable<RouteTransitionRecord> resolve({
List<RouteTransitionRecord> newPageRouteHistory,
Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
}) {
final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];
for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
if (pageRoute.isEntering) {
pageRoute.markForAdd();
}
results.add(pageRoute);
}
for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
exitingPageRoute.markForRemove();
final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
if (pagelessRoutes != null) {
for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
pagelessRoute.markForRemove();
}
}
results.add(exitingPageRoute);
}
return results;
}
}
遷移後的程式碼:
import 'package:flutter/widgets.dart';
class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
@override
Iterable<RouteTransitionRecord> resolve({
List<RouteTransitionRecord> newPageRouteHistory,
Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
}) {
final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];
for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
// Renames isEntering to isWaitingForEnteringDecision.
if (pageRoute.isWaitingForEnteringDecision) {
pageRoute.markForAdd();
}
results.add(pageRoute);
}
for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
// Checks the isWaitingForExitingDecision before calling the markFor methods.
if (exitingPageRoute.isWaitingForExitingDecision) {
exitingPageRoute.markForRemove();
final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
if (pagelessRoutes != null) {
for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
pagelessRoute.markForRemove();
}
}
}
results.add(exitingPageRoute);
}
return results;
}
}
時間軸
#
導入版本:1.18.0
穩定版本:1.20
參考資料
#API 文件:
相關議題:
相關 PR:
- PR 55998:修正當仍有 Route 等待時,Navigator 頁面更新導致的閃退問題
Unless stated otherwise, the documentation on this site reflects Flutter 3.44.0. Page last updated on 2026-06-14. View source or report an issue.