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

Flutter使用awesome_select报错:S2SingleSelection释放后仍被调用

解决S2SingleSelection已释放后仍被使用的错误

问题根源

错误出在自定义choiceBuilder的两个GestureDetector逻辑中:你手动修改_selectedLevel并调用setState,同时又调用item.onModalClose(true)和item.closeModal()关闭模态。这种操作会导致组件状态更新与模态关闭逻辑冲突——模态关闭后内部的S2SingleSelection实例已被释放,但后续的setState触发组件重建时,会试图再次使用已释放的实例,从而抛出错误。

解决方案

1. 复用组件内置的选择逻辑

不要手动处理选择状态和模态关闭,而是交给SmartSelect.single的onChange回调和item.onTap()方法处理,这是组件设计的标准用法,能避免状态不一致。

2. 移除冗余无效代码

删除选择逻辑中手动更新状态、关闭模态的代码,以及删除逻辑中无效的setState(() { isSelected.value; });语句。

修改后的完整代码

String? _selectedLevel;

final firestore = FirebaseFirestore.instance;

SmartSelect.single(
  selectedValue: _selectedLevel,
  onChange: (newValue) {
    setState(() {
      _selectedLevel = newValue.value;
    });
  },
  choiceItems: documents.map((DocumentSnapshot<dynamic> dataDoc) {
    return S2Choice(
      value: dataDoc.data()['field1'],
      title: dataDoc.data()['field1'],
    );
  }).toList(),
  placeholder: 'N/A',
  tileBuilder: (context, value) {
    return Container(
      padding: EdgeInsets.symmetric(
        vertical: MediaQuery.of(context).size.height * 0.01,
        horizontal: MediaQuery.of(context).size.width * 0.03,
      ),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.onPrimary,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Row(
        children: [
          Padding(
            padding: EdgeInsets.symmetric(
              horizontal: MediaQuery.of(context).size.width * 0.035,
            ),
            child: Icon(
              FontAwesomeIcons.locationDot,
              color: Theme.of(context).colorScheme.primary,
              size: MediaQuery.of(context).size.width * 0.065,
            ),
          ),
          Expanded(
            child: S2Tile(
              value: Text(
                _selectedLevel != null ? "" : "",
                style: TextStyle(
                  color: Theme.of(context).colorScheme.primary,
                  fontSize: MediaQuery.of(context).size.width * 0.055,
                ),
              ),
              onTap: () {
                value.showModal();
              },
              title: Text(
                _selectedLevel != null ? _selectedLevel! : "Choose",
                style: TextStyle(
                  fontSize: MediaQuery.of(context).size.width * 0.055,
                  color: Theme.of(context).colorScheme.primary,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
              loadingText: "",
              trailing: Icon(
                FontAwesomeIcons.angleDown,
                color: Theme.of(context).colorScheme.primary,
              ),
            ),
          )
        ],
      ),
    );
  },
  modalConfig: const S2ModalConfig(
    title: '',
    type: S2ModalType.bottomSheet,
  ),
  choiceConfig: S2ChoiceConfig(
    type: S2ChoiceType.radios,
    style: S2ChoiceStyle(
      showCheckmark: true,
      color: Theme.of(context).colorScheme.primary,
      titleStyle: TextStyle(
        fontSize: MediaQuery.of(context).size.width * 0.055,
        color: Theme.of(context).colorScheme.primary,
      ),
    ),
  ),
  choiceBuilder: (context, item, isSelected) {
    return Padding(
      padding: EdgeInsets.symmetric(
        vertical: MediaQuery.of(context).size.height * 0.015,
        horizontal: MediaQuery.of(context).size.width * 0.03,
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          // 使用组件内置onTap处理选择逻辑
          GestureDetector(
            onTap: item.onTap,
            child: Row(
              children: [
                Icon(
                  _selectedLevel == isSelected.value ? FontAwesomeIcons.solidCircleCheck : FontAwesomeIcons.circle,
                  color: Theme.of(context).colorScheme.primary,
                  size: MediaQuery.of(context).size.width * 0.055,
                ),
                SizedBox(
                  width: MediaQuery.of(context).size.width * 0.05,
                ),
                Text(
                  isSelected.value,
                  style: TextStyle(
                    overflow: TextOverflow.ellipsis,
                    fontSize: MediaQuery.of(context).size.width * 0.055,
                    color: Theme.of(context).colorScheme.primary,
                  ),
                ),
              ],
            ),
          ),
          Row(
            children: [
              GestureDetector(
                onTap: () {
                  // TODO EDIT NAME SITE
                },
                child: Icon(
                  FontAwesomeIcons.penToSquare,
                  color: Theme.of(context).colorScheme.primary,
                  size: MediaQuery.of(context).size.width * 0.055,
                ),
              ),
              SizedBox(
                width: MediaQuery.of(context).size.width * 0.05,
              ),
              GestureDetector(
                onTap: () {
                  if (isSelected.value != null) {
                    CRUDMethodFirestore(
                      selectedLevel: isSelected.value,
                      itemModal: item,
                      context: context,
                    ).delete();
                  }
                  setState(() {
                    _selectedLevel = null;
                  });
                },
                child: Icon(
                  FontAwesomeIcons.trash,
                  color: Theme.of(context).colorScheme.primary,
                  size: MediaQuery.of(context).size.width * 0.055,
                ),
              ),
            ],
          )
        ],
      ),
    );
  },
),

关键修改说明

  • 选择区域的GestureDetector直接绑定item.onTap,让组件内部完成选择、状态更新和模态关闭的全流程,避免手动操作导致的实例释放冲突。
  • 删除了选择逻辑中手动设置_selectedLevel和调用item.onModalClose、item.closeModal的代码。
  • 移除了删除逻辑中无效的setState语句。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:45:36