You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击悬浮按钮后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无需修改。


修改后逻辑说明

  1. LoadUserEvent携带页码参数,让Bloc能动态获取不同页的数据
  2. UserBloc不再依赖构造参数的页码,而是从事件中获取,支持动态切换
  3. 点击按钮时通过context.read<UserBloc>()获取已存在的Bloc实例,发送事件,确保BlocBuilder监听的实例能收到状态更新
  4. 移除重复的BlocProvider,避免多个Bloc实例冲突

内容的提问来源于stack exchange,提问作者Quick learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:03:24