点击悬浮按钮后BlocBuilder未重建的问题及代码示例
Flutter Bloc点击按钮无法更新ListView的解决方案
问题根源
- 点击按钮时新建了
UserBloc实例,而非获取BlocProvider中已存在的实例,导致BlocBuilder监听的实例未收到事件 UserBloc将pageNo作为构造参数固化,无法动态切换页码- HomePage的
blocBody方法中重复创建UserBloc,与上层MultiBlocProvider提供的实例冲突
修改步骤及代码
1. 修改UserEvent,新增带页码参数的事件
@immutable abstract class UserEvent extends Equatable { const UserEvent(); } class LoadUserEvent extends UserEvent { final String pageNo; const LoadUserEvent(this.pageNo); @override List<Object?> get props => [pageNo]; }
2. 修改UserBloc,移除构造参数中的页码,从事件获取页码
class UserBloc extends Bloc<UserEvent, UserState> { final UserRepository _userRepository; UserBloc(this._userRepository) : super(UserLoadingState()) { on<LoadUserEvent>((event, emit) async { emit(UserLoadingState()); try { final users = await _userRepository.getUsers(event.pageNo); emit(UserLoadedState(users)); } catch (e) { emit(UserErrorState(e.toString())); } }); } }
3. 修改HomePage,复用已存在的Bloc实例并发送带参数的事件
class HomePage extends StatelessWidget { String pageNo = "1"; @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider<UserBloc>( create: (BuildContext context) => UserBloc(UserRepository())..add(LoadUserEvent(pageNo)), ), ], child: Scaffold( appBar: AppBar(title: const Text('The BloC App')), body: blocBody(), floatingActionButton: FloatingActionButton( onPressed: () { pageNo = "2"; context.read<UserBloc>().add(LoadUserEvent(pageNo)); }, child: const Icon(Icons.navigation), ), ), ); } Widget blocBody() { return BlocBuilder<UserBloc, UserState>( builder: (context, state) { if (state is UserLoadingState) { return const Center( child: CircularProgressIndicator(), ); } if (state is UserLoadedState) { List<UserModel> userList = state.users; return ListView.builder( itemCount: userList.length, itemBuilder: (_, index) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), child: Card( color: Theme.of(context).primaryColor, child: ListTile( title: Text( '${userList[index].firstName} ${userList[index].lastName}', style: const TextStyle(color: Colors.white), ), subtitle: Text( '${userList[index].email}', style: const TextStyle(color: Colors.white), ), leading: CircleAvatar( backgroundImage: NetworkImage( userList[index].avatar.toString()), ))), ); }); } if (state is UserErrorState) { return const Center( child: Text("Error"), ); } return Container(); }, ); } }
4. 其他文件保持不变
UserState、UserModel、UserRepository、main.dart无需修改。
修改后逻辑说明
LoadUserEvent携带页码参数,让Bloc能动态获取不同页的数据UserBloc不再依赖构造参数的页码,而是从事件中获取,支持动态切换- 点击按钮时通过
context.read<UserBloc>()获取已存在的Bloc实例,发送事件,确保BlocBuilder监听的实例能收到状态更新 - 移除重复的BlocProvider,避免多个Bloc实例冲突
内容的提问来源于stack exchange,提问作者Quick learner
相关产品推荐
相关产品推荐

