使用Cubit时视图未更新 点击左表行无法刷新右表数据
问题原因
右侧表格不刷新是三个问题叠加导致的:
- 状态类
TaskState配置错误:一是枚举名混用,定义的是TaskStatus,代码里全用不存在的AllDataStatus,状态判断逻辑根本不生效;二是Equatable的props列表只加了task字段,没加status,Bloc靠props做状态差分比对,status变化时不会触发组件重绘;三是命名构造方法写的是AllDataState,和类名TaskState不匹配,属于语法错误。 - Bloc注册缺失:
MultiBlocProvider里只注册了TableACubit、TableBCubit,没有注册TaskCubit,行点击逻辑拿到的Cubit实例和BlocBuilder监听的实例不是同一个,状态变更通知传不到Builder。 - 字段笔误:BlocBuilder的success分支里取的是
state.taskDetails,但TaskState里根本没有定义这个字段,拿不到新数据。
修复方案
按以下步骤改完即可正常联动刷新:
- 第一步:重写
TaskState类,统一命名,补全props列表
enum TaskStatus { loading, success, failure } class TaskState extends Equatable { final TaskStatus status; final Task? task; TaskState({ this.status = TaskStatus.loading, this.task, }); factory TaskState.loading() => TaskState(); factory TaskState.success(Task task) => TaskState(status: TaskStatus.success, task: task); factory TaskState.failure() => TaskState(status: TaskStatus.failure); // 必须把status和task都放进props,状态变化才能被Bloc识别 @override List<Object?> get props => [status, task]; }
- 第二步:在
MultiBlocProvider中补全TaskCubit的注册,保证全局使用的是同一个Cubit实例
MultiBlocProvider( providers: [ BlocProvider<TableACubit>( create: (context) => TableACubit()..getData(a, b), ), BlocProvider<TableBCubit>( create: (context) => TableBCubit(), ), // 补上TaskCubit注册 BlocProvider<TaskCubit>( create: (context) => TaskCubit(), ), ], child: TableAState(task: task,), );
- 第三步:修正
TaskCubit的状态发射逻辑,确保请求全流程都有对应状态抛出
class TaskCubit extends Cubit<TaskState> { TaskCubit() : super(TaskState.loading()); Future<void> getTasks(int taskId) async { // 触发加载态,显示loading emit(TaskState.loading()); try { // 替换成你实际的接口/数据查询逻辑 final Task newTaskData = await yourApi.getTaskDetailById(taskId); // 拿到数据后发成功态,携带新数据 emit(TaskState.success(newTaskData)); } catch (err) { // 请求异常发失败态 emit(TaskState.failure()); } } }
- 第四步:修正BlocBuilder的状态判断和字段取值,去掉笔误
BlocBuilder<TaskCubit, TaskState>( builder: (context, state) { switch (state.status) { case TaskStatus.failure: return const Center(child: Text('数据加载失败')); case TaskStatus.success: return FDView( // 取state里实际存在的task字段传值 taskData: state.task!, isExpanded: isExpanded, keyTile: keyTile, ); case TaskStatus.loading: default: return const Loader(); } } ),
额外注意:如果
FDView是StatefulWidget,不要给它传全局固定的ValueKey,否则Widget会被持久复用,不会随新数据重绘。
内容的提问来源于stack exchange,提问作者M.A.
相关产品推荐
相关产品推荐

