flutter go_router 出现 Riverpod 重定向异常/位置不能为空。 / 未通知重定向

问题描述 投票:0回答:1

我正在使用 Riverpod 作为状态管理来开发我的应用程序,并且我使用了

go_router 
包进行路由管理,专门用于将用户重定向到刷新令牌更新失败的登录页面。 所以我想要的是我想在重定向方法中观看我的
refreshTokenViewModel 
,这样如果
refreshTokenState 
失败,我想将用户重定向到登录页面。

问题是没有通知重定向方法。我知道,当我再次尝试再次访问该页面时(状态现已更新),我被重定向到登录页面。 请参考此视频:视频链接

因此,当我第一次在未经授权的情况下尝试访问任何页面时,我得到:

======== Exception caught by foundation library ====================================================
The following GoException was thrown while dispatching notifications for GoRouteInformationProvider:
Location cannot be empty.

When the exception was thrown, this was the stack: 
#0      canonicalUri (package:go_router/src/path_utils.dart:125:5)
#1      RouteConfiguration.findMatch (package:go_router/src/configuration.dart:296:31)
#2      _RouteMatchListDecoder.convert (package:go_router/src/match.dart:947:23)
#3      Codec.decode (dart:convert/codec.dart:30:34)
#4      GoRouteInformationParser.parseRouteInformationWithDependencies (package:go_router/src/parser.dart:71:32)
#5      _RouterState._processRouteInformation (package:flutter/src/widgets/router.dart:749:8)
#6      _RouterState._handleRouteInformationProviderNotification (package:flutter/src/widgets/router.dart:767:5)
#7      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:433:24)

但是当尝试再次访问它时,我被重定向了。

我整天在互联网上搜索此类异常,但一无所获。

我尝试过的:

路由器提供商:

final _key = GlobalKey<NavigatorState>();

final routerProvider = Provider<GoRouter>((ref) {

***//when using watch the app remain stuck on the splash page*  **
   final authState = ref.read(refreshTokenViewModelProvider);

  return GoRouter(
    navigatorKey: _key,
    debugLogDiagnostics: true,
    initialLocation: '/',
    refreshListenable: authState, ***//with/without it nothing changed***
    routes: [....],
    errorBuilder: (context, state) =>
        const Center(child: CircularProgressIndicator()),
    redirect: (context, state) {
*//cannot watch provider here Cannot use ref functions after the dependency of a provider changed but before the provider rebuilt*
      bool isRefreshTokenFailure = (authState.refreshTokenState == RefreshTokenState.failure);
      if (isRefreshTokenFailure) {
        return "/login";
      } else {
        return null;
      }
    },
  );
});

主要小部件构建方法 不知道该用什么,都不起作用。

 routeInformationParser: router.routeInformationParser,
 routeInformationProvider: router.routeInformationProvider,
 routerDelegate: router.routerDelegate,

或:

routerConfig: ref.watch(routerProvider),
@override
  Widget build(BuildContext outContext) {
      ref.watch(themeRProvider);
      return MaterialApp.router(
        routerConfig: ref.watch(routerProvider),
        // routeInformationParser: router.routeInformationParser,
        // routeInformationProvider: router.routeInformationProvider,
        // routerDelegate: router.routerDelegate,
        themeMode: themeProvider.themeMode == ThemeModeOption.light
            ? ThemeMode.light
            : themeProvider.themeMode == ThemeModeOption.dark
                ? ThemeMode.dark
                : ThemeMode.system,
        theme: lightTheme,
        darkTheme: darkTheme,
        // home: SplashPage(),
      );
  }

refreshTokenViewModelProvider 的片段:

enum RefreshTokenState { initial, loading, success, failure , networkFailure}
class RefreshTokenViewModel extends ChangeNotifier {
  RefreshTokenState _refreshTokenViewModelState = RefreshTokenState.initial;
  RefreshTokenState get refreshTokenState => _refreshTokenViewModelState;

  setFailure(UserError error) {
    _refreshTokenViewModelState = RefreshTokenState.failure;
    notifyListeners();
  }

Future<void> refreshToken() async {
    var response = await refreshTokenRepository.refreshToken();
    if (response is Failure) {
      setFailure(UserError(response.errorMessage));
    } else {
      setSuccess();
    }
  }

}
flutter dart authentication routes mvvm
1个回答
0
投票

您需要创建一个本地

ValueNotifier
,它将作为
refreshListenable
传递到路由器。使用
ref.listen
收听
refreshTokenViewModelProvider
并用它更新
ValueNotifier

final routerProvider = Provider<GoRouter>((ref) {
  final authStateNotifier = ValueNotifier(RefreshTokenState.initial);
  ref
    ..onDispose(authStateNotifier.dispose)
    ..listen(refreshTokenViewModelProvider, (_, value) {
      authStateNotifier.value = value;
    });

  // ...

  return GoRouter(
    // ...
    refreshListenable: authStateNotifier,
    redirect: (_, state) {
      final authState = ref.read(refreshTokenViewModelProvider);
      // ...
    },

请参阅完整示例此处

© www.soinside.com 2019 - 2024. All rights reserved.