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

Flutter多选组件报错:setState() called after dispose()

问题分析

出现setState() called after dispose()错误的核心原因:

  • FutureBuilder重复创建Future:每次父组件触发setState(比如普通下拉选择时),FutureBuilder都会重新调用Provider.of<Salesmans>(context, listen: false).getUser()生成新Future,导致旧的MultiSelectField被销毁。
  • 多选对话框回调关联已销毁组件:如果此时多选对话框仍处于打开状态,确认选择时的onConfirm回调会试图操作已销毁的组件状态,触发错误。
  • 额外冗余:普通下拉的onChanged中存在无意义的_selectedRoles;代码,可直接删除。
解决方案

1. 缓存Future避免重复执行

将获取用户的Future存储在父组件状态中,确保FutureBuilder只执行一次:

// 父组件State类中添加变量
Future<Salesman> _userFuture;

@override
void initState() {
  super.initState();
  // 在initState中初始化Future,避免每次build重复调用
  _userFuture = Provider.of<Salesmans>(context, listen: false).getUser();
}

// 替换原有FutureBuilder
FutureBuilder(
  future: _userFuture, // 使用缓存的Future
  builder: (BuildContext context, AsyncSnapshot<Salesman> snapshot) {
    // 原有逻辑保持不变
    if (snapshot.connectionState == ConnectionState.done) {
      return MultiSelectField<DdlValues>(
        // ... 其他属性
      );
    } else {
      return CircularProgressIndicator();
    }
  },
),

2. 给MultiSelectField添加稳定Key

设置固定Key,确保父组件重建时,该组件不会被销毁重建,而是更新现有实例:

// 父组件State类中定义Key
final _multiSelectKey = GlobalKey<MultiSelectFieldState<DdlValues>>();

// 在MultiSelectField中使用该Key
return MultiSelectField<DdlValues>(
  key: _multiSelectKey,
  initialValue: _selectedRoles,
  buttonText: 'Select Roles',
  title: 'Select Roles',
  stream: _listRoles,
  onConfirm: (values) {
    // 确保父组件仍挂载时再更新状态
    if (mounted) {
      setState(() {
        _selectedRoles = values;
      });
    }
  },
);

3. 完善MultiSelectField的状态安全

在自定义MultiSelectField中,确保回调仅在组件挂载时执行:

// 修改MultiSelectField中的MultiSelectDialogField配置
return MultiSelectDialogField(
  buttonText: Text(widget.buttonText),
  title: Text(widget.title),
  items: widget.stream
      .map((item) => MultiSelectItem(item, item.name))
      .toList(),
  initialValue: widget.initialValue,
  onConfirm: (values) {
    // 检查当前组件是否仍挂载
    if (mounted) {
      widget.onConfirm(values);
    }
  },
  listType: MultiSelectListType.LIST,
  validator: (List value) {
    if (value?.isEmpty ?? true) {
      return 'Please select Roles ';
    }
    return null;
  },
);

4. 清理冗余代码

删除普通下拉onChanged中的无意义代码:

onChanged: (String value) {
  if (mounted) {
    setState(() {
      dropdownValueLvl = value;
      // 移除该行:_selectedRoles;
    });
  }
},
验证效果

完成上述修改后,父组件触发setState时,FutureBuilder不会重新创建MultiSelectField,多选对话框的回调只会关联活跃的组件实例,从而避免setState() called after dispose()错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:05:44