BlocListener无法监听LoginCubit发出的状态,登录后无法跳转
登录状态发射后BlocListener未执行跳转的问题
问题描述
期望实现流程:
- 点击登录按钮
- 完成登录流程
- 登录成功后跳转到指定页面
当前问题:即使LoginCubit中已成功发出LoginState.success()状态(已在Cubit内校验该状态相等性为true),BlocListener的listener代码从未被执行。使用freezed库生成状态,寻求实现遗漏点。
代码片段
LoginCubit代码
class LoginCubit extends CubitBase<LoginState>{ LoginCubit() : super(const LoginState.created()); Future<void> runLoginFlow() async { final isAuthorized = await startAuth(); if(isAuthorized){ emit(const LoginState.success()); } emit(const LoginState.failed(failedLogin)); } Future<bool> startAuth() async { //doing some stuff } }
状态代码(freezed生成)
@freezed class LoginState with _$LoginState{ const factory LoginState.created() = _Created; const factory LoginState.failed(String message) = _Failed; const factory LoginState.success() = _Success; }
UI代码
@RoutePage() class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return BlocProvider<LoginCubit>( create: (context) => LoginCubit(), child: Scaffold( body: BlocListener<LoginCubit, LoginState>( listener: (context, state) { if(state == LoginState.success()){ AutoRouter.of(context).navigate(NextPageRoute()) } }, bloc: LoginCubit(), child: _buildContent(context), ), ), ); } }
问题修复要点
Cubit实例不匹配
UI代码中BlocProvider创建了一个LoginCubit实例,但BlocListener的bloc参数又新建了另一个独立实例,导致监听的Cubit从未触发目标状态。
修复:移除BlocListener的bloc参数,让它自动从上下文获取BlocProvider提供的实例:BlocListener<LoginCubit, LoginState>( listener: (context, state) { if(state == LoginState.success()){ AutoRouter.of(context).navigate(NextPageRoute()); } }, child: _buildContent(context), )状态被瞬间覆盖
LoginCubit的runLoginFlow方法中,即使isAuthorized为true,emit成功状态后紧接着又emit失败状态,导致成功状态被快速覆盖,BlocListener无法捕获。
修复:在成功分支添加return,避免后续状态发射:Future<void> runLoginFlow() async { final isAuthorized = await startAuth(); if(isAuthorized){ emit(const LoginState.success()); return; // 添加此行终止方法 } emit(const LoginState.failed(failedLogin)); }优化状态判断方式
虽然直接用==判断freezed生成的状态可行,但更推荐使用freezed提供的pattern matching,代码更清晰且不易出错:listener: (context, state) { state.when( created: () {}, failed: (message) {}, success: () { AutoRouter.of(context).navigate(NextPageRoute()); }, ); },
内容的提问来源于stack exchange,提问作者toledo1366
相关产品推荐
相关产品推荐

