Flutter Bloc问题:状态变更后BlocBuilder未再次调用builder方法
解决Flutter Bloc主题切换时UI不更新的问题
从你的日志和代码来看,问题的核心原因是**ThemeBloc被重复创建了**,导致状态更新的Bloc和UI监听的Bloc不是同一个实例,所以后续的状态变更无法触发BlocBuilder的重建。
问题分析
你把BlocProvider放在了_MyAppState的build方法内部:
@override Widget build(BuildContext context) { return BlocProvider( create: (context) => ThemeBloc(), child: BlocBuilder<ThemeBloc, ThemeState>(...) ); }
当第一次切换主题时,MaterialApp的theme变化会触发MyApp的build方法重新执行,这时候会创建一个全新的ThemeBloc实例。而你的按钮点击事件获取的是之前的旧ThemeBloc实例,后续的状态更新都发送到了旧Bloc里,但UI监听的是新创建的Bloc,自然不会触发UI更新。
从日志也能看出来:第一次切换到BlueLight时builder日志打印了,之后切换到GreenDark时只有ThemeBloc的日志,没有builder的日志,说明新的Bloc没有收到状态变更,而旧Bloc的状态更新无法被新的BlocBuilder捕获。
解决方案
把BlocProvider提升到MyApp的外部,确保整个应用只有一个ThemeBloc实例,避免重复创建。具体步骤如下:
- 将
MyApp改为StatelessWidget(或者保持StatefulWidget但把BlocProvider移到父级,避免在build方法内重复创建) - 在
runApp中直接包裹BlocProvider,让整个应用共享同一个ThemeBloc实例
修改后的代码示例
主入口部分
void main() { runApp( BlocProvider( create: (context) => ThemeBloc(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return BlocBuilder<ThemeBloc, ThemeState>( builder: (context, state) { print("builder " + state.toString()); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Bitradez', routes: routes, theme: state.themeData, ); }, ); } }
ThemeBloc部分(保持不变)
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> { ThemeBloc() : super(ThemeState(themeData: appThemeData[AppTheme.GreenLight])); @override Stream<ThemeState> mapEventToState( ThemeEvent event, ) async* { print("ThemeBloc " + (event as ThemeChanged).theme.toString()); if (event is ThemeChanged) { print("ThemeBloc isThemeChange"); yield ThemeState(themeData: appThemeData[event.theme]); } } }
按钮点击事件(保持不变)
onTap: () { print("_ChangeThemeScreenState " + itemAppTheme.toString()); BlocProvider.of<ThemeBloc>(context) .add(ThemeChanged(theme: itemAppTheme)); },
为什么这样能解决问题
现在ThemeBloc只在应用启动时创建一次,所有UI组件(包括BlocBuilder和按钮)都共享同一个Bloc实例。当按钮发送事件更新状态时,BlocBuilder会监听同一个Bloc的状态变化,每次状态变更都会触发builder方法重新执行,UI也会随之更新。
内容的提问来源于stack exchange,提问作者Đăng Huấn
相关产品推荐
相关产品推荐

