如何解决推送通知写入数据库仅保留最后一条的实时更新问题?
看起来你遇到的问题是每次Firebase推送过来,你把数据存在变量里,但没有立刻写入数据库,结果新推送覆盖了旧变量值,等你回到应用时只存了最后一条对吧?我来帮你梳理下怎么解决:
核心问题定位
你现在的逻辑是「接收推送→存变量→应用恢复时写入数据库」,但这个流程里变量是单次存储的,新推送会直接覆盖旧值,自然最后只保留最后一条。要实现数据库实时更新,关键是每次收到推送就立刻执行写入操作,而不是先存在变量里等后续处理。
具体修改步骤
针对你的Firebase Messaging Service代码,调整如下:
- 移除中间变量,收到推送直接写库
把原本存变量的代码,替换成直接调用数据库插入方法。比如你的Service类里的OnMessageReceived方法:
[Service] [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] public class MyFirebaseMessagingService : FirebaseMessagingService { public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); // 1. 解析推送数据(根据你的payload结构调整) var pushData = new PushNotificationModel { MessageId = message.MessageId, // 用Firebase的唯一ID避免重复 Title = message.GetNotification()?.Title ?? message.Data["title"], Body = message.GetNotification()?.Body ?? message.Data["body"], ReceivedTime = DateTime.Now, // 其他自定义字段... }; // 2. 立刻写入数据库,而不是存在变量里 _ = DatabaseHelper.InsertPushNotificationAsync(pushData); // 3. 如需展示通知,处理前台/后台的通知展示逻辑 SendLocalNotification(pushData); } }
- 把数据库操作放到后台线程
数据库写入是IO操作,不能在Service的主线程执行,否则可能导致ANR或者性能问题。所以要把写库逻辑封装成异步方法:
// 数据库帮助类的异步插入方法 public static async Task InsertPushNotificationAsync(PushNotificationModel model) { await Task.Run(() => { using(var db = new SQLiteConnection(DbPath)) { db.CreateTable<PushNotificationModel>(); // 先检查是否已存在,避免重复写入 var existing = db.Table<PushNotificationModel>() .FirstOrDefault(x => x.MessageId == model.MessageId); if(existing == null) { db.Insert(model); } } }); }
- 处理后台推送的特殊情况
如果应用在后台,Firebase可能不会触发OnMessageReceived,而是直接展示系统通知。这种情况下,用户点击通知打开应用时,你需要从Intent里提取推送数据并写入数据库:
- 在MainActivity的
OnNewIntent方法里处理:
protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); if(intent.Extras != null) { var pushData = new PushNotificationModel { MessageId = intent.Extras.GetString("google.message_id"), Title = intent.Extras.GetString("title"), Body = intent.Extras.GetString("body"), ReceivedTime = DateTime.Now }; _ = DatabaseHelper.InsertPushNotificationAsync(pushData); } }
- 同时,推送payload要包含
data字段(而非仅notification),这样后台推送时数据才能传递到应用:
{ "data": { "title": "新消息提醒", "body": "这是一条测试推送", "custom_key": "自定义值" }, "to": "你的设备Token" }
额外注意事项
- 数据库实例管理:确保数据库路径在Service和Activity中都能正常访问,比如把路径设为全局常量,或者用依赖注入统一管理数据库实例。
- 异常处理:可以给数据库操作加上try-catch,避免因写入失败导致Service崩溃:
public static async Task InsertPushNotificationAsync(PushNotificationModel model) { try { await Task.Run(() => { // 数据库写入逻辑 }); } catch(Exception ex) { // 记录日志或处理异常 Console.WriteLine($"写入数据库失败: {ex.Message}"); } }
这样调整后,每次收到推送(不管前台还是后台)都会立刻把数据写入数据库,不会再出现只保留最后一条的情况,数据库也能实现实时更新啦!
内容的提问来源于stack exchange,提问作者Владимир
相关产品推荐
相关产品推荐

