Flutter Bloc状态变更后UI未更新问题求助
问题根源
你代码的核心问题是没有监听Bloc的状态变化——你只是在build时读取了一次CounterBloc的当前状态,但Bloc状态更新后,没有任何机制通知UI重新构建。context.read<T>()只会获取当前状态,不会订阅状态变化。
修复方案
我们需要用BlocBuilder组件来包裹依赖Bloc状态的UI部分,它会自动监听Bloc的状态更新,并在状态变化时重建内部widget。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; // Counter event. abstract class CounterEvent {} class Increment extends CounterEvent {} // Counter bloc: Recive a event and increase the count. class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((Increment event, Emitter<int> emit) { print('Send state: ${state + 1}'); emit(state + 1); }); } } // Home page event and bloc here, just as a placeholder. class HomeEvent {} class HomeBloc extends Bloc<HomeEvent, int> { HomeBloc() : super(0) { on<HomeEvent>((HomeEvent event, Emitter<int> emit) => emit(state + 1)); } } // The parent widget, create a home bloc. class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) => BlocProvider<HomeBloc>( create: (BuildContext context) => HomeBloc()..add(HomeEvent()), child: Builder( builder: _getHome, )); Widget _getHome(BuildContext context) => Scaffold( appBar: AppBar(title: const Text('Frame')), body: CounterPage(), ); } // Our counter page, use bloc provider to create a new bloc. class CounterPage extends StatelessWidget { const CounterPage({super.key}); @override Widget build(BuildContext context) => BlocProvider<CounterBloc>( create: (BuildContext context) => CounterBloc(), child: BlocBuilder<CounterBloc, int>( builder: (context, state) { // 根据当前状态返回对应UI return Center( child: AddWidget(count: state), ); }, )); } // As the sub widget, use the counter bloc from context. class AddWidget extends StatelessWidget { const AddWidget({required this.count, super.key}); final int count; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '$count', style: const TextStyle(fontSize: 24), ), const SizedBox(height: 20), FloatingActionButton( child: const Icon(Icons.add), onPressed: () { print('Send increment event.'); context.read<CounterBloc>().add(Increment()); }, ) ], ), ); } }
关键修改点
- 替换Builder为BlocBuilder:在
CounterPage中,用BlocBuilder<CounterBloc, int>替代原来的Builder,这样每当CounterBloc的状态更新时,builder方法会自动调用,UI随之重建。 - 简化CounterPage的实现:将
CounterPage改为无状态组件,直接在BlocProvider的create方法中初始化CounterBloc,不需要在State中存储实例,避免内存管理问题。 - 直接传递Bloc状态:在
BlocBuilder的builder参数中直接获取当前状态state,传递给AddWidget,确保UI显示最新值。
额外说明
- 如果需要更精细的状态监听(比如只在特定状态变化时更新),可以给
BlocBuilder添加buildWhen参数,例如:
这样只有当状态变为偶数时,才会触发UI重建。BlocBuilder<CounterBloc, int>( buildWhen: (previous, current) => current % 2 == 0, builder: (context, state) { ... }, )
内容的提问来源于stack exchange,提问作者yt heel
相关产品推荐
相关产品推荐

