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

Flutter中使用MobX @observable与Observer时UI不更新的问题排查

问题分析与解决方案

核心错误点

1. 组件构造函数参数绑定错误

QuizzOptionButtons的构造函数中,isSelected参数未正确绑定到组件成员变量:

// 错误写法
required widget.isSelected
// 正确写法应该是
required this.isSelected

这个错误导致组件无法接收外部传入的选中状态,无论MobX状态如何变化,组件的isSelected始终未被正确赋值,UI自然不会更新。

2. onSelect方法逻辑混乱

  • 先执行optionsSelecteds[index] = !optionsSelecteds[index]切换当前选项状态,随后立刻通过循环强制将当前选项设为选中、其他选项设为未选中,完全覆盖了之前的操作,逻辑矛盾。
  • 未区分单选和多选场景,不管是否开启多选,都执行单选逻辑,导致多选功能完全失效。

3. 冗余方法调用

页面中同时调用ChangeSelectedOptions和onSelect,但onSelect内部已经处理了selectedOption的赋值,前者属于冗余操作。


修正后的代码

1. 修复QuizzOptionButtons构造函数

class QuizzOptionButtons extends StatefulWidget {
  final String title;
  final bool isSelected;
  final List<dynamic>? options;
  final int index;
  final VoidCallback onTap;
  final bool isMultipleChoice;

  const QuizzOptionButtons({
    Key? key,
    required this.title,
    required this.isSelected, // 修正为this.isSelected
    required this.onTap,
    this.isMultipleChoice = false,
    required this.options,
    required this.index,
  }) : super(key: key);

  // ... 其余代码不变
}

2. 重构onSelect方法,区分单选/多选逻辑

@action
void onSelect(int index, List<dynamic> options, bool isMultipleChoice) {
  if (isMultipleChoice) {
    // 多选:切换当前选项的选中状态
    optionsSelecteds[index] = !optionsSelecteds[index];
    labelSelecteds[index] = optionsSelecteds[index] ? options[index] : '';
  } else {
    // 单选:仅选中当前选项,其余全部取消
    for (int i = 0; i < optionsSelecteds.length; i++) {
      if (i == index) {
        optionsSelecteds[i] = true;
        labelSelecteds[i] = options[index];
        selectedOption = options[index];
      } else {
        optionsSelecteds[i] = false;
        labelSelecteds[i] = '';
      }
    }
  }
}

3. 简化页面中的onTap逻辑

移除冗余的ChangeSelectedOptions调用:

onTap: () {
  controller.onSelect(index, widget.options!, widget.isMultipleChoice!);
  debugPrint(widget.options![index]);
  debugPrint(controller.optionsSelecteds.toString());
  debugPrint(controller.labelSelecteds.toString());
},

4. 确保状态初始化时机(可选)

在页面的State类中,确保问卷选项变化时重新初始化选中状态列表:

@override
void initState() {
  super.initState();
  controller.isSelectedList(widget.options!, widget.isMultipleChoice!);
}

@override
void didUpdateWidget(covariant YourPageWidget oldWidget) {
  super.didUpdateWidget(oldWidget);
  if (oldWidget.options != widget.options) {
    controller.isSelectedList(widget.options!, widget.isMultipleChoice!);
  }
}

验证效果

修正后,点击选项时:

  • 单选模式下,只会选中当前选项,其他选项自动取消选中
  • 多选模式下,可自由切换单个选项的选中状态
  • UI会根据MobX中的optionsSelecteds状态实时更新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:26:01