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

Flutter Bloc处理点击事件仅生效一次问题求助

我来帮你排查这个Bloc点击无响应的问题,核心原因其实和Equatable的状态对比逻辑有关:

问题根源

Bloc内部有个关键逻辑:如果新生成的状态和当前状态相等,就不会将这个状态发送给UI。而你的HandleDrawerMenuClick状态类没有正确实现Equatable的属性对比规则:

看你的HandleDrawerMenuClick代码:

class HandleDrawerMenuClick extends HomeState{
  @override
  String toString()=>'HandleDrawerMenuClick';
}

它继承自HomeState,但没有给Equatable的props传递任何唯一标识。这意味着每次你yield HandleDrawerMenuClick()时,Equatable都会判定这两个实例是完全相等的(因为props是空列表,对比结果一致)。第一次点击时,初始状态是HomeState(),和HandleDrawerMenuClick不同,所以UI会响应;但第二次点击时,新状态和当前状态都是HandleDrawerMenuClick且被判定为相等,Bloc就会忽略这个状态更新,自然不会触发UI的打印逻辑。

修复方案

只需要给HandleDrawerMenuClick添加一个唯一属性,让Equatable能区分不同的状态实例即可。最简单的方式是加入时间戳:

class HandleDrawerMenuClick extends HomeState{
  final DateTime timestamp;

  HandleDrawerMenuClick() 
    : timestamp = DateTime.now(),
      super([DateTime.now()]); // 这里也可以直接传timestamp到父类props

  @override
  List<Object> get props => [timestamp];

  @override
  String toString()=>'HandleDrawerMenuClick';
}

或者如果不需要额外数据,用随机值也能达到效果:

import 'dart:math';

class HandleDrawerMenuClick extends HomeState{
  HandleDrawerMenuClick() : super([Random().nextInt(999999)]);

  @override
  List<Object> get props => super.props;

  @override
  String toString()=>'HandleDrawerMenuClick';
}

额外的优化建议

  1. 移除重复的MaterialApp:你的App类已经是根MaterialApp的home,但MainPage的build方法又返回了一个新的MaterialApp,这会导致上下文嵌套混乱。建议直接返回Scaffold:
@override
Widget build(BuildContext context) {
  return BlocBuilder<HomeEvent,HomeState>(
    bloc: _homeBloc,
    builder: (BuildContext context, HomeState state) {
      if (state is HandleDrawerMenuClick) {
        _onWidgetDidBuild(() {
          print("clicked on drawer menu");
        });
      }
      return Scaffold(
        body: Center(
          child: RaisedButton(
            child: Text('ddddddddd'),
            onPressed: () {
              _homeBloc.add(OnDrawerMenuClicked()); // 注意:新版Bloc用add替代dispatch
            },
          ),
        ),
      );
    },
  );
}
  1. 更新Bloc API:你当前用的dispatch是旧版API,最新的Bloc库已经改用add方法,建议同步更新。

这样修改后,每次点击按钮都会生成一个唯一的状态实例,Bloc会正确发送状态更新,你的控制台就能每次都打印出点击日志了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:01:20