如何使用flutter_bloc 8+、go_router +6和refreshListenable

Phi*_*ume 8 dart firebase-authentication flutter flutter-bloc flutter-go-router

我使用 go_router 进行导航,使用 flutter_bloc 进行状态管理。

我想使用refreshListenable并在我的GoRouter配置中监听我的AuthBloC事件,但是,我无权访问我的GoRouter中的上下文,并且我不想提供它。

我发现的大多数答案都已过时,或者使用 StreamBuilder 等替代方案在事件更改时重新渲染整个应用程序,这并不理想。

如何在上下文之外监听我的 AuthEvents?

主程序.dart

return RepositoryProvider.value(
      value: authRepo,
      child: BlocProvider(
        create: (_) => AuthBloc(authRepo),
        child: MaterialApp.router(
          ...
          routerConfig: Routes.router,
          builder: (_, child) {
            final isRTL = LocaleSettings.currentLocale == AppLocale.ar;

            return Directionality(
              textDirection: isRTL ? TextDirection.rtl : TextDirection.ltr,
              child: child!,
            );
          },
        ),
      ),
Run Code Online (Sandbox Code Playgroud)

块/auth/auth_bloc.dart

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  AuthBloc(this._authenticationRepository) : super(const AuthState()) {
    on<AuthEvent>((event, emit) {
      event.when(
        authStateChangeEvent: (account) => _authStateChangeEvent(account, emit),
        signOutEvent: _signOutEvent,
        verifyAccount: _verifyAccount,
      );
    });
    _userSubscription = _authenticationRepository.user.listen((account) {
      add(AuthEvent.authStateChangeEvent(account));
    });
  }

  late final StreamSubscription<Account> _userSubscription;
  final AuthenticationRepository _authenticationRepository;

  void _authStateChangeEvent(
    Account account,
    Emitter<AuthState> emit,
  ) {
   ...
  }

  void _signOutEvent() {
   ...
  }

  void _verifyAccount() {
    ...
  }

  @override
  Future<void> close() {
    _userSubscription.cancel();

    return super.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

路由器.dart

class Routes {
  Routes._();

  static final _rootNavigatorKey = GlobalKey<NavigatorState>();

  static GoRouter get router => _router;

  static final GoRouter _router = GoRouter(
    navigatorKey: _rootNavigatorKey,
    refreshListenable: , // ! Listen to Auth Changes
    routes: [..._directNavigations, ..._nestedNavigations],
    redirect: _authGuard, //
  );

  static String? _authGuard(BuildContext context, GoRouterState state) {
    final authState = context.watch<AuthBloc>().state;
    print(authState.toString());

    final isAuthenticated = authState.authStatus == AuthStatus.authenticated;
    final isVerified =
        authState.account != null && authState.account!.emailVerified;
    
    /// ... Some logic for redirection
   
    return null;
  }
  
  ...
}
Run Code Online (Sandbox Code Playgroud)

当我使用 context.go/context.push 导航时遇到此错误

"Tried to listen to a value exposed with provider, from outside of the widget tree.\n\nThis is
js_primitives.dart:30 likely caused by an event handler (like a button's onPressed) that called\nProvider.of without
js_primitives.dart:30 passing `listen: false`.\n\nTo fix, write:\nProvider.of<AuthBloc>(context, listen: false);\n\nIt is
js_primitives.dart:30 unsupported because may pointlessly rebuild the widget associated to the\nevent handler, when the
js_primitives.dart:30 widget tree doesn't care about the value.\n\nThe context used was:
js_primitives.dart:30 Navigator-[LabeledGlobalKey<NavigatorState>#31496](dependencies: [HeroControllerScope,
js_primitives.dart:30 UnmanagedRestorationScope, _FocusTraversalGroupMarker], state: NavigatorState#795d6(tickers:
js_primitives.dart:30 tracking 1 ticker))\n"
Run Code Online (Sandbox Code Playgroud)

完整的崩溃日志: https: //pastebin.com/3A3pdKtr

注意:我愿意用更改通知程序替换我的 Auth BloC,但我不确定这是否是处理此问题的正确方法。