Flutter Navigator 2.0:从外部访问RouterDelegate状态
方案一:直接访问 RouterDelegate 并更新状态
你可以通过 Router.of(context).routerDelegate 获取到 RouterDelegate 的实例,直接调用其内部方法更新状态,关键是要调用 notifyListeners() 触发 currentConfiguration 的更新,这样路由系统才能感知到状态变化并同步路由配置。
示例代码:
// 自定义 RouterDelegate class BookRouterDelegate extends RouterDelegate<BookRoutePath> with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath> { Book? _selectedBook; final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); // 暴露更新选中书籍的方法 void selectBook(Book book) { _selectedBook = book; notifyListeners(); // 必须调用,触发路由配置更新 } @override BookRoutePath get currentConfiguration { return _selectedBook == null ? BookRoutePath.home() : BookRoutePath.details(books.indexOf(_selectedBook!)); } // 实现其他 Navigator 2.0 必需方法(如 build、setNewRoutePath 等) }
在组件树下层的 Widget 中调用:
ElevatedButton( onPressed: () { // 强转为自定义的 RouterDelegate 类型 final delegate = Router.of(context).routerDelegate as BookRouterDelegate; delegate.selectBook(targetBook); }, child: const Text('查看书籍详情'), )
方案二:将状态抽离到外部类(复用 Provider + ChangeNotifier)
如果希望状态与 RouterDelegate 解耦,或者需要在多个组件间共享状态,可以把 _selectedBook 这类状态抽成独立的 ChangeNotifier 类,让 RouterDelegate 监听该状态的变化,同步更新路由配置。
1. 定义独立的状态类
class BookState extends ChangeNotifier { Book? _selectedBook; Book? get selectedBook => _selectedBook; void selectBook(Book book) { _selectedBook = book; notifyListeners(); } void clearSelectedBook() { _selectedBook = null; notifyListeners(); } }
2. 在 RouterDelegate 中依赖并监听状态
class BookRouterDelegate extends RouterDelegate<BookRoutePath> with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath> { final BookState bookState; late final VoidCallback _stateListener; final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); BookRouterDelegate(this.bookState) { // 监听 BookState 变化,触发路由配置更新 _stateListener = () => notifyListeners(); bookState.addListener(_stateListener); } @override void dispose() { bookState.removeListener(_stateListener); super.dispose(); } @override BookRoutePath get currentConfiguration { return bookState.selectedBook == null ? BookRoutePath.home() : BookRoutePath.details(books.indexOf(bookState.selectedBook!)); } @override Future<void> setNewRoutePath(BookRoutePath path) async { // 路由跳转时同步更新外部状态 if (path.isDetailsPage) { if (path.id! >= 0 && path.id! < books.length) { bookState.selectBook(books[path.id!]); } } else { bookState.clearSelectedBook(); } } // 实现其他 Navigator 2.0 必需方法 }
3. 在下层 Widget 中通过 Provider 更新状态
ElevatedButton( onPressed: () { // 通过 Provider 获取状态实例并更新 Provider.of<BookState>(context, listen: false).selectBook(targetBook); }, child: const Text('查看书籍详情'), )
方案选择建议
- 若路由状态仅与导航逻辑强相关,用方案一更直接,无需额外状态类;
- 若状态需要在多个非路由组件中共享,或者希望路由逻辑与业务状态解耦,方案二更符合分层设计原则。
内容的提问来源于stack exchange,提问作者alexlipa
相关产品推荐
相关产品推荐

