flutter_bloc与HydratedBloc中BlocListener不监听状态变化排查
问题:BlocListener无法监听HydratedBloc的状态变化
我正在使用flutter_bloc库和HydratedBloc创建Auth bloc,目前遇到的问题是BlocListener无法监听状态变化,我猜测问题可能是fromJson函数返回的初始状态未触发新状态发射,以下是我的实现代码:
class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider(create: (context) => AuthBloc()), ], child: MaterialApp( debugShowCheckedModeBanner: false, theme: Themes.light, darkTheme: Themes.dark, themeMode: ThemeMode.dark, title: AppContants.appName, navigatorKey: NavigationService.navigatorKey, onGenerateRoute: Routes.navigateTo, builder: (BuildContext context, Widget? child) { child = EasyLoading.init()(context, child); return BlocListener<AuthBloc, AuthState>( listener: (context, AuthState state) { //bloc listener is used to make a actions instead of builds //bloc bulder is used to return a widget print('state is $state'); if (state is AuthAuthenticatedState) { // NavigationService.navigateAndRemoveUntil(Confirm.route); NavigationService.navigateAndRemoveUntil( Dashboard.route, ); } else { NavigationService.navigateAndRemoveUntil(Login.route); } }, child: child); }, )); } } class AuthBloc extends HydratedBloc<AuthEvent, AuthState> { AuthBloc() : super(AuthInitial()) { on<AuthAuthenticatingEvent>(authAuthenticating); on<AuthUnAuthenticatingEvent>(authUnAuthenticating); } authAuthenticating(event, emit) async { await Future.delayed(const Duration(seconds: 1)); emit(const AuthAuthenticatedState('')); } authUnAuthenticating(event, emit) {} @override AuthState? fromJson(Map<String, dynamic> json) { String? token = json['token']; if (token != null && token.isNotEmpty) { return AuthAuthenticatedState(token); } return AuthUnAuthenticatedState(); } @override Map<String, dynamic>? toJson(AuthState state) { if (state is AuthAuthenticatedState) { return {'token': state.token}; } return {}; } }
问题原因及解决方案
核心问题
HydratedBloc在初始化时,会通过fromJson加载持久化状态并直接替换初始状态,但这个过程不会触发emit操作,因此BlocListener无法监听到这个状态变化(BlocListener仅响应通过emit发射的状态)。
具体修复步骤
- 在AuthBloc中重写
onHydrated方法,手动emit加载后的状态
当HydratedBloc完成持久化状态加载后,onHydrated会被调用,此时手动emit当前状态即可触发BlocListener的监听逻辑:
class AuthBloc extends HydratedBloc<AuthEvent, AuthState> { AuthBloc() : super(AuthInitial()) { on<AuthAuthenticatingEvent>(authAuthenticating); on<AuthUnAuthenticatingEvent>(authUnAuthenticating); } // ... 原有方法保持不变 @override void onHydrated() { // 手动emit加载后的状态,触发BlocListener emit(state); super.onHydrated(); } }
- 优化BlocListener的跳转逻辑,避免循环跳转
当前代码每次状态变化都会强制跳转页面,可能导致重复跳转(比如已在Dashboard时再次收到AuthAuthenticatedState),建议添加路由判断:
BlocListener<AuthBloc, AuthState>( listener: (context, AuthState state) { print('state is $state'); final currentRoute = NavigationService.navigatorKey.currentContext?.route.settings.name; if (state is AuthAuthenticatedState) { if (currentRoute != Dashboard.route) { NavigationService.navigateAndRemoveUntil(Dashboard.route); } } else { if (currentRoute != Login.route) { NavigationService.navigateAndRemoveUntil(Login.route); } } }, child: child, )
- 可选:调整初始状态与持久化状态的一致性
由于fromJson返回的状态会覆盖构造函数中传入的AuthInitial,可以将构造函数的初始状态改为与fromJson的默认返回一致,避免状态混淆:
AuthBloc() : super(AuthUnAuthenticatedState()) { // ... 原有逻辑 }
内容的提问来源于stack exchange,提问作者guru
相关产品推荐
相关产品推荐

