You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Navigator 2.0:从外部访问RouterDelegate状态

Flutter Navigator 2.0 状态管理与路由配置更新方案

方案一:直接访问 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:24:22