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

如何在ListView.builder中配置独立的CustomPopupMenuController

解决ListView.builder中custom_pop_up_menu控制器复用问题

问题根源

你当前的写法核心错误是把CustomPopupMenuController实例转成字符串传入模型类,这完全不是插件需要的控制器实例;同时复用同一个_controller对象,导致所有列表项共用同一控制器,弹窗状态混乱。

正确实现方案

不需要额外的模型类,直接维护一个List<CustomPopupMenuController>即可,每个列表项对应独立的控制器实例:

1. 初始化控制器列表

// 直接用List存储控制器,无需额外封装
List<CustomPopupMenuController> controllers = [];

2. 加载数据时创建独立控制器

在getAllMessages方法中,每添加一条交易数据,同时创建新的控制器实例:

void getAllMessages() {
  Future.delayed(Duration.zero, () async {
    List<SmsMessage> messages = await query.querySms(
      kinds: [SmsQueryKind.inbox],
      count: 200,
      address: "MPESA",
    );

    setState(() {
      transactions.clear();
      controllers.clear(); // 清空旧控制器避免冗余
      allmessages = messages;

      for (var element in allmessages) {
        String message = element.body.toString();

        if ((RawData.getMode(message) == 1 ||
                RawData.getMode(message) == 2 ||
                RawData.getMode(message) == 3 ||
                RawData.getMode(message) == 4) &&
            RawData.getTime(message) != 'ERR') {
          transactions.add(
            TransData(
              receiver: RawData.getReceiver(message),
              code: RawData.getTransactionCode(message),
              amount: RawData.getAmount(message),
              paymentMode: RawData.getModeName(message),
              time: RawData.getTime(message),
              date: RawData.getDate(message),
              phone: RawData.getSendMonmeyNumber(message),
              accountNumber: RawData.getPayBillAccountNumber(message),
              message: message,
            ),
          );
          // 为当前列表项创建全新的控制器实例
          controllers.add(CustomPopupMenuController());
        }
      }
    });
  });
}

3. 在ListView.builder中绑定对应控制器

通过列表索引获取当前项的控制器:

ListView.builder(
  itemCount: transactions.length,
  itemBuilder: (context, index) {
    final itemController = controllers[index];
    return CustomPopupMenu(
      controller: itemController,
      menuBuilder: () => // 你的自定义菜单布局,
      child: // 列表项UI组件,
    );
  },
)

4. 清理控制器避免内存泄漏

在页面销毁时,遍历列表释放所有控制器资源:

@override
void dispose() {
  for (var controller in controllers) {
    controller.dispose();
  }
  super.dispose();
}

可选:保留自定义模型类的写法

如果一定要用你定义的MyCustomPopupController,修正使用逻辑即可:

// 模型类保持不变
class MyCustomPopupController {
  final CustomPopupMenuController controller;
  MyCustomPopupController({required this.controller});
}

// 初始化列表
List<MyCustomPopupController> controllers = [];

// 添加控制器时传入新实例
controllers.add(MyCustomPopupController(controller: CustomPopupMenuController()));

// ListView中调用
final itemController = controllers[index].controller;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:13:25