Flutter接入FCM接收推送时通知列表旧值被新值覆盖重复如何解决
问题根因定位
你遇到的列表条目内容完全重复、旧通知被新值覆盖的问题,本质是Dart中的对象引用传递机制和复用同一个通知实例的逻辑共同导致的:
- 代码中使用的
widget._localNotificationList是提前初始化好的成员级类实例。第一次收到推送时,你修改这个实例的title、body属性后,把这个实例加入notifList——此时列表中存储的并不是当前通知的内容快照,而是这个实例的内存引用。 - 第二次收到新推送时,你没有创建新的通知实例,依旧修改原
_localNotificationList的属性,再把同一个引用再次加入列表。此时列表的两个位置都存储了指向同一块内存的引用,修改这块内存里的内容时,所有指向它的列表项都会同步读取到最新的属性值,最终表现为两个条目内容完全一致。
修复方案
- 每次收到推送时,禁止复用同一个通知实例,必须基于当前收到的消息内容创建独立的新通知对象,再加入列表:
调整后的FCM消息处理逻辑如下:FirebaseMessaging.onMessage.listen((RemoteMessage message) async { if (message.notification != null) { // 每次创建全新的独立通知实例,不复用旧的成员变量 final newNotification = LocalNotificationList( title: message.notification!.title ?? '无标题', body: message.notification!.body ?? '无内容', // 可同步绑定FCM消息自带的唯一messageId,方便后续做去重、删除逻辑 uniqueId: message.messageId ?? DateTime.now().millisecondsSinceEpoch.toString(), ); // 将新实例加入列表 widget._pushDecode.notifList.add(newNotification); savePush(); setState(() {}); } }); - 优化列表渲染的效率和可靠性:当前代码在
itemBuilder中每次构建条目时都会调用notifList.reversed.elementAt(i),这个操作会在每次构建时生成新的反转迭代器,不仅有性能浪费,还容易在列表动态变更时出现索引错位。可以将反转后的列表提前转成局部常量,再按索引取值:// 提前生成反转后的通知列表,避免重复计算 final displayNotifications = widget._pushDecode.notifList.reversed.toList(); ListView.builder( itemCount: displayNotifications.length, itemBuilder: (context, i) { final currentNotif = displayNotifications[i]; // 反向列表对应的原列表索引为 总长度 - 1 - i final originalIndex = widget._pushDecode.notifList.length - 1 - i; return Card( margin: EdgeInsets.all(10), elevation: 4, child: ListTile( trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => removePush(originalIndex), ), title: Text(currentNotif.title), subtitle: Text(currentNotif.body), ), ); }, ) - 可选优化:给通知模型增加唯一标识字段,后续做重复推送去重、单条删除定位时逻辑会更严谨,避免出现索引错位的bug。
内容的提问来源于stack exchange,提问作者Kaya Ryuuna
相关产品推荐
相关产品推荐

