使用AutoRoute与Riverpod实现导航守卫时遇到报错问题
问题分析与解决方案
核心错误点
- guards参数类型错误:你在
AutoRoute的guards数组里传入了AuthGuard类本身,但auto_route要求传入**AutoRouteGuard的实例**,而非类型。 - 依赖注入问题:
AuthGuard依赖Riverpod的Ref,无法在AppRouter的routes配置中直接实例化,因为AppRouter初始化时还未进入ProviderScope上下文。 - onNavigation逻辑无效:
onNavigation是void类型方法,你内部的maybeMap返回bool不会产生任何导航控制效果,必须通过NavigationResolver和StackRouter来执行实际的导航逻辑。
修正步骤
1. 修复AuthGuard的导航控制逻辑
修改onNavigation方法,根据登录状态执行允许导航或跳转登录页的操作:
class AuthGuard extends AutoRouteGuard { final Ref _ref; AuthGuard(this._ref); @override void onNavigation(NavigationResolver resolver, StackRouter router) async { // 监听登录状态(同步状态直接watch,异步状态需用future) final authState = _ref.watch(authNotifierProvider); authState.maybeMap( authenticated: (_) { // 已登录,允许访问目标页面 resolver.resolve(true); }, orElse: () { // 未登录,跳转到登录页,登录成功后重新尝试导航 router.push(SignInRoute(onResult: (isSuccess) { isSuccess ? resolver.resolve(true) : resolver.resolve(false); })); }, ); } }
2. 修改AppRouter,通过构造函数注入AuthGuard实例
让AppRouter接收外部传入的AuthGuard实例,避免在routes配置中直接依赖:
class AppRouter extends _$AppRouter { final AuthGuard authGuard; AppRouter(this.authGuard); @override List<AutoRoute> get routes => [ AutoRoute( page: SplashRoute.page, initial: true, ), // 传入已初始化的authGuard实例 AutoRoute(page: StarredRepoRoute.page, guards: [authGuard]), AutoRoute(page: SignInRoute.page), AutoRoute(page: AuthorizationRoute.page), ]; // 修正isInitialRoute为getter(原方法写法不符合auto_route要求) @override bool get isInitialRoute => false; }
3. 在main函数中正确初始化AppRouter
通过Riverpod容器获取AuthGuard实例,再传入AppRouter:
void main() { runApp( ProviderScope( child: Builder( builder: (context) { // 从Provider容器中读取AuthGuard实例 final authGuard = ProviderScope.containerOf(context).read(authGuardProvider); return MaterialApp.router( routerDelegate: AutoRouterDelegate( AppRouter(authGuard), navigatorObservers: () => [AutoRouteObserver()], ), routeInformationParser: AppRouter(authGuard).defaultRouteParser(), ); }, ), ), ); }
额外注意事项
- 如果
authNotifierProvider是AsyncNotifier,需使用_ref.watch(authNotifierProvider.future)来等待状态加载完成,避免处理loading状态时的异常。 - 登录页的
onResult回调需要在登录成功后返回true,通知守卫允许继续导航。
内容的提问来源于stack exchange,提问作者Akhil
相关产品推荐
相关产品推荐

