在 Flutter 中,如果你使用的是 Navigator 来管理页面路由(即使用 Navigator.push 等方式),没有直接的内置 API 可以判断“某个 Widget 是否已经被 push 并正在展示”,因为:
- Flutter 的导航是基于 Route 的,而不是基于 Widget 的。
- 一个 Widget 是否“正在展示”取决于它是否在当前活动的 Route 中,并且该 Route 是否在导航栈的顶层。
那么我们怎么办呢?使用Navigator.pushNamed:
方法 1:使用 NavigatorObserver(全局监听)
你可以创建一个自定义的 NavigatorObserver,在其中记录当前显示的 Route:
class MyRouteObserver extends NavigatorObserver {
// 单例代码略
Route? currentRoute;
@override
void didPush(Route route, Route? previousRoute) {
currentRoute = route;
print('Pushed: ${route.settings.name}');
}
@override
void didPop(Route route, Route? previousRoute) {
currentRoute = previousRoute;
print('Popped: ${route.settings.name}');
}
}
然后在 MaterialApp 中注册它:
MaterialApp(
navigatorObservers: [MyRouteObserver单例],
// ...
);
之后你可以在任何地方访问 MyRouteObserver单例.currentRoute 来判断当前页面。
方法 3:使用 RouteAware(更精细控制)
Flutter 提供了 RouteAware 和 RouteObserver,可以让 Widget 自己感知生命周期:
class PageRouteObserver extends RouteObserver {
String? currentRouteName;
// 私有构造函数
PageRouteObserver._internal();
// 静态实例,Dart 中只会初始化一次
static final PageRouteObserver _instance = PageRouteObserver._internal();
// 工厂构造函数,返回唯一实例
factory PageRouteObserver() => _instance;
static PageRouteObserver get instance => _instance;
}
同样,别忘了在 MaterialApp 中注册 routeObserver:
MaterialApp(
navigatorObservers: [routeObserver],
// ...
)
再创建RouteAwareState
abstract class RouteAwareState<T extends StatefulWidget> extends State<T>
with RouteAware {
// push/pop life circle
@override
void didChangeDependencies() {
super.didChangeDependencies();
PageRouteObserver.instance.subscribe(this, ModalRoute.of(context)!);
}
@override
void dispose() {
PageRouteObserver.instance.unsubscribe(this);
super.dispose();
}
@override
void didPush() {
// 当前页面被 push
PageRouteObserver.instance.currentRouteName = ModalRoute.of(
context,
)?.settings.name;
}
@override
void didPopNext() {
// 从其他页面返回
PageRouteObserver.instance.currentRouteName = ModalRoute.of(
context,
)?.settings.name;
}
@override
void didPushNext() {
// 跳转到其他页面
}
@override
void didPop() {
// 当前页面被 pop
}
}
所有PageState继承RouteAwareState,StatelessWidget 原理也是一样。
最后使用方法如下:
String? routeName = PageRouteObserver.instance.currentRouteName;
✅ 总结
| 方法 | 是否推荐 | 说明 |
|---|---|---|
NavigatorObserver |
✅ 全局监听 | 适合跨页面逻辑 |
RouteAware |
✅ 精细控制 | 适合 Widget 自己感知生命周期 |
| 判断某个 Widget 是否“正在展示” | ❌ 不可行 | Flutter 没有 Widget 层级的“展示”状态 |