我应该在 FirebaseMessagingService 的 onMessageReceived() 中使用协程吗?

Should I use coroutine in onMessageReceived() of FirebaseMessagingService?

我正在使用 MVVM 设计模式开发 Android 应用程序。

我有一个 class FCMService 扩展 FirebaseMessagingService.

如您所知,FCMService 覆盖 onMessageReceived(remoteMessage: RemoteMessage) 函数。

因此,每当我在 onMessageReceived() 函数中收到一条消息时,我想通过存储库将其保存到房间数据库中。

看起来像下面的代码。

class FCMService : FirebaseMessagingService(), KodeinAware {

    override val kodein by closestKodein()
    private val repository: Repository by instance()
    private val scope: CoroutineScope by instance()

    override fun onNewToken(token: String) {
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        CoroutineScope(Dispatchers.IO).lauch{ repository.save(remoteMessage) }
    }
}
class Repository {
   suspend fun save(remoteMessage: RemoteMessage) {
      withContext(Dispatchers.IO) {
         someDAO.save(removeMessage)
      }
   }
}

我阅读了 Whosebug 并发现 onMessageReceived() 函数在后台线程中执行,并且在 onMessageReceived(RemoteMessage message) 中完成的所有工作都应该同步完成。

所以,这是我的问题

  1. 我应该在 onMessageRecevied() 函数中使用 CoroutineScope(Dispatchers.IO).lauch {} 吗?

  2. 如果没有,那么我可以只使用正常功能,而不是在存储库中暂停功能,我可以从 onMessageReceived() 调用它而不用 CoroutineScope(Dispatchers.IO).launch {}。请问从架构设计的角度来说是否正确?

  3. 这是一个关于 Coroutine 的问题,但是,正如你所看到的,我在 FCMService 中通过 CoroutineScope(Dispatchers.IO).lauch{ repository.save(remoteMessage) } 在 IO 线程中启动了一个新的协程,但我也从 IO 切换了 coroutineContext通过 withContext(Dispatchers.IO) { someDAO.save(removeMessage) }Repository 到 IO。我觉得withContext(Dispatchers.IO) { someDAO.save(removeMessage) }是不必要的,因为我是从IO切换到IO。请问我说的对吗?

我会尽我所知尽力回答。现在来回答你的问题。

Should I use CoroutineScope(Dispatchers.IO).lauch {} in onMessageRecevied() function?

我不认为它有任何问题。 Firebase Messaging Service 基本上仍然是一个服务,所以应该没有问题。我建议您创建一个 Coroutine 范围,如果出现任何问题,您可以取消该范围。通常在 ViewModel 中我们使用 viewModelScope

所以你可以这样做

val job = SupervisorJob()

 CoroutineScope(job).launch { 
   // Your Stuff here 
}

override fun onDestroy() {
    job.cancel()
    super.onDestroy()
}

第二个问题

If no, then I can just use normal function, not suspend function in repository and I can call it from onMessageReceived() without CoroutineScope(Dispatchers.IO).launch {}. Is it correct in terms of architectural design point of view please?

我建议您仍然使用协程作用域,而不是直接使用普通函数,因为无论如何都建议使用带有协程的 Room,即使从架构的角度来看也不会造成伤害。

第三

It's a question about Coroutine but, as you can see that I launched a new coroutine in IO thread by CoroutineScope(Dispatchers.IO).lauch{ repository.save(remoteMessage) } in FCMService but I also switch the coroutineContext from IO to IO by withContext(Dispatchers.IO) { someDAO.save(removeMessage) } in Repository. I feel that withContext(Dispatchers.IO) { someDAO.save(removeMessage) } is unnecessary because I am switching from IO to IO. Am I right please?

既然您已经在使用 Dispatchers.IO,您就不再需要它了,这是正确的。让它保持 withContext(Dispatcher.IO) 只是为了与您的其他结构保持一致。