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

结合Navigator 2.0处理导航状态应选用哪种Riverpod Provider?

Riverpod + Navigator 2.0 集成方案与Provider选型指南

核心集成逻辑

Navigator 2.0(Router API)的核心机制是RouterDelegate根据当前状态动态构建路由栈,和Riverpod的集成逻辑非常直接:将全局路由状态完全托管给Riverpod管理,在RouterDelegate中通过ref.watch监听路由状态变化,状态更新时自动触发路由栈重绘即可,不需要额外的桥接逻辑。

Provider选型对比

ChangeNotifierProvider适用场景

  • 选择依据:你的导航逻辑需要维护多个可变属性(除路由栈外还要存跳转参数、动画配置、拦截状态等),且你更习惯原生端传统的观察者更新模式
  • 优势:写法直观门槛低,调用notifyListeners()即可触发更新,不需要强制状态不可变
  • 劣势:没有状态修改的统一入口,可变状态容易出现难以追溯的逻辑bug,不适合多人协作的中大型项目

StateNotifierProvider适用场景

  • 选择依据:希望路由状态为不可变类型,所有状态修改都走统一的方法入口,需要做路由行为埋点、日志追溯
  • 优势:强制immutable状态,所有状态变更可追溯,逻辑更可控,适合中大型项目
  • 劣势:需要单独定义状态类和StateNotifier子类,代码量稍高

更优选型推荐

如果是Riverpod 2.0及以上版本,官方首推NotifierProvider作为StateNotifierProvider的替代方案,写法更简洁,同时保留了不可变状态的所有优势,是当前处理导航状态的最优选择。
如果你的项目逻辑非常简单,仅需要维护路由栈列表,也可以直接用StateProvider<List<AppRoute>>,不需要定义任何类,直接修改state即可完成路由跳转,适合小型轻量化项目。

最简实现示例

// 1. 定义全局路由枚举
enum AppRoute { home, detail, settings }

// 2. 定义不可变路由状态
@immutable
class AppRouterState {
  final List<AppRoute> routeStack;
  final Map<String, dynamic>? currentRouteParams;
  const AppRouterState({required this.routeStack, this.currentRouteParams});
}

// 3. 定义路由操作Notifier
class AppRouterNotifier extends Notifier<AppRouterState> {
  @override
  AppRouterState build() => const AppRouterState(routeStack: [AppRoute.home]);

  // 压入新页面
  void push(AppRoute route, {Map<String, dynamic>? params}) {
    state = AppRouterState(
      routeStack: [...state.routeStack, route],
      currentRouteParams: params,
    );
  }

  // 弹出当前页面
  void pop() {
    if (state.routeStack.length <= 1) return;
    state = AppRouterState(
      routeStack: state.routeStack.sublist(0, state.routeStack.length - 1),
    );
  }

  // 替换当前页面
  void replace(AppRoute route, {Map<String, dynamic>? params}) {
    state = AppRouterState(
      routeStack: [...state.routeStack.sublist(0, state.routeStack.length - 1), route],
      currentRouteParams: params,
    );
  }
}

// 4. 定义路由Provider
final appRouterProvider = NotifierProvider<AppRouterNotifier, AppRouterState>(AppRouterNotifier.new);

// 5. 自定义RouterDelegate监听状态
class AppRouterDelegate extends RouterDelegate<AppRouterState> with ChangeNotifier, PopNavigatorRouterDelegateMixin {
  final WidgetRef ref;
  AppRouterDelegate(this.ref);

  @override
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    final routerState = ref.watch(appRouterProvider);
    return Navigator(
      key: navigatorKey,
      pages: routerState.routeStack.map((route) {
        switch(route) {
          case AppRoute.home:
            return const MaterialPage(child: HomePage(), name: 'home');
          case AppRoute.detail:
            return MaterialPage(child: DetailPage(params: routerState.currentRouteParams), name: 'detail');
          case AppRoute.settings:
            return const MaterialPage(child: SettingsPage(), name: 'settings');
        }
      }).toList(),
      onPopPage: (route, result) {
        if (!route.didPop(result)) return false;
        ref.read(appRouterProvider.notifier).pop();
        return true;
      },
    );
  }

  @override
  Future<void> setNewRoutePath(AppRouterState configuration) async {
    state = configuration;
  }
}

在业务页面中需要跳转时,直接调用ref.read(appRouterProvider.notifier).push(AppRoute.detail, params: {'id': 123})即可。

内容的提问来源于stack exchange,提问作者CKP78

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 00:15:04