Flutter Bloc问题:触发新事件后状态未更新,导航失效
问题修复方案
核心问题:多Bloc实例导致状态不共享
你代码里存在两个完全独立的AppBloc实例:
- 在
_MyAppState中手动初始化了appBloc变量,按钮点击时用它发送NavigatorButtonPressed事件 - 但
BlocProvider的create方法又新建了另一个AppBloc,BlocListener和BlocBuilder实际监听的是这个Provider内的实例
两个实例状态完全隔离,所以手动调用appBloc.add(...)触发的状态变化,Provider里的BlocListener根本感知不到。
修复步骤:
- 移除手动创建的Bloc实例,统一使用
BlocProvider提供的实例 - 删除BlocBuilder内重复发送事件的代码,避免无限重绘循环
- 确保事件触发和状态监听使用同一个Bloc实例
修复后的完整代码
1. Bloc代码(无需修改)
import 'package:bloc/bloc.dart'; import 'package:bloctest/bloc/events.dart'; import 'package:bloctest/bloc/states.dart'; class AppBloc extends Bloc<AppEvent,AppState>{ AppBloc(AppState initialState):super(initialState){ on<AppStartEvent>((event, emit) { emit(AppInitState()); }); on<NavigatorButtonPressed>((event, emit) { emit(NavigationSucceedState()); print('navigation succeed'); }); } }
2. BlocListener页面(修复后)
import 'package:bloctest/bloc/bloc.dart'; import 'package:bloctest/bloc/states.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'bloc/events.dart'; import 'main2.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) { return MaterialApp( home: BlocProvider<AppBloc>( create: (context) => AppBloc(AppInitState())..add(AppStartEvent()), child: Scaffold( body: BlocListener<AppBloc, AppState>( listener: (context, state) async { if (state is NavigationSucceedState) { await Future.delayed(const Duration(seconds: 1)); Navigator.push(context, MaterialPageRoute(builder: (context) => MyApp2())); } }, child: BlocBuilder<AppBloc, AppState>( builder: (context, state) { return state is AppStartingState ? const Center(child: CircularProgressIndicator()) : Scaffold( body: SafeArea( child: Center( child: ElevatedButton( onPressed: () => context.read<AppBloc>().add(NavigatorButtonPressed()), child: const Text('点击跳转到下一页'), ), ), ), ); }, ), ), ), ), ); } }
额外说明
BlocProvider的核心作用是在Widget树中共享Bloc实例,所有子Widget必须通过context.read()或context.watch()获取同一个实例,才能保证状态同步- 绝对不要在BlocBuilder的build方法内发送事件,否则每次Widget重绘都会触发事件,导致无限循环和严重性能问题
内容的提问来源于stack exchange,提问作者Abdulmateen Maher
相关产品推荐
相关产品推荐

