如何在AlarmReceiver接收闹钟时调用Room的upsertNotification操作数据库?
实现AlarmReceiver接收闹钟时向Room数据库插入数据
要在AlarmReceiver中调用Room的upsertNotification方法,需要解决两个核心问题:获取Room的DAO实例和在后台线程执行挂起函数,以下是具体实现方案:
方案一:直接使用协程(快速实现)
借助Hilt注入DAO,并通过协程在IO线程执行数据库操作:
1. 修改AlarmReceiver代码
给AlarmReceiver添加Hilt注解,注入NotificationDao,并在协程中执行插入操作:
@AndroidEntryPoint class AlarmReceiver : BroadcastReceiver() { @Inject lateinit var notificationDao: NotificationDao override fun onReceive(context: Context?, intent: Intent?) { val message = intent?.getStringExtra("EXTRA_MESSAGE") ?: return val notificationType = NotificationType.fromValue(intent.getIntExtra("NOTIFICATION_TYPE", 0)) // 构造要插入的Notification对象(注意使用intent传递的通知类型) val notification = Notification( id = null, date = LocalDate.now(), time = LocalTime.now(), title = "Test Title Premium", description = message, unread = true, notificationType = notificationType.value ) // 在IO线程执行数据库挂起函数 CoroutineScope(Dispatchers.IO).launch { notificationDao.upsertNotification(notification) } // 原有通知展示逻辑 context?.let { DayReminderNotificationService(it) }?.showNotification(message) } }
关键注意事项
- 确保你的Application类已添加
@HiltAndroidApp注解,否则Hilt无法正常注入依赖。 - 协程方式适合短耗时操作,但如果
onReceive执行完成后进程被系统回收,可能导致数据库操作中断。
方案二:使用WorkManager(可靠保障)
如果需要确保数据库操作一定完成,推荐使用WorkManager,即使进程被杀,系统也会重新调度任务:
1. 创建NotificationInsertWorker
@HiltWorker class NotificationInsertWorker @AssistedInject constructor( @Assisted context: Context, @Assisted params: WorkerParameters, private val notificationDao: NotificationDao ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { // 从输入数据中获取参数 val message = inputData.getString("EXTRA_MESSAGE") ?: return Result.failure() val notificationTypeValue = inputData.getInt("NOTIFICATION_TYPE", 0) val notificationType = NotificationType.fromValue(notificationTypeValue) // 构造Notification对象 val notification = Notification( id = null, date = LocalDate.now(), time = LocalTime.now(), title = "Test Title Premium", description = message, unread = true, notificationType = notificationType.value ) // 执行数据库操作 return try { notificationDao.upsertNotification(notification) Result.success() } catch (e: Exception) { // 失败后可重试 Result.retry() } } }
2. 修改AlarmReceiver调度WorkManager任务
@AndroidEntryPoint class AlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val message = intent?.getStringExtra("EXTRA_MESSAGE") ?: return val notificationTypeValue = intent.getIntExtra("NOTIFICATION_TYPE", 0) // 构造WorkRequest并传递参数 val workRequest = OneTimeWorkRequestBuilder<NotificationInsertWorker>() .setInputData( Data.Builder() .putString("EXTRA_MESSAGE", message) .putInt("NOTIFICATION_TYPE", notificationTypeValue) .build() ) .build() // 调度任务 WorkManager.getInstance(context!!).enqueue(workRequest) // 原有通知展示逻辑 context.let { DayReminderNotificationService(it) }.showNotification(message) } }
关键注意事项
- 需添加WorkManager与Hilt的依赖(根据你的Gradle版本调整)。
- WorkManager会自动处理后台任务的生命周期,确保操作最终完成。
内容的提问来源于stack exchange,提问作者SkAppCoding
相关产品推荐
相关产品推荐

