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

Kis*_*Tae 6 android coroutine firebase-cloud-messaging

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

我有一个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) }
    }
}
Run Code Online (Sandbox Code Playgroud)
class Repository {
   suspend fun save(remoteMessage: RemoteMessage) {
      withContext(Dispatchers.IO) {
         someDAO.save(removeMessage)
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

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

所以,这是我的问题

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

  2. 如果不是,那么我可以只使用普通函数,而不是存储库中的挂起函数,并且我可以从onMessageReceived()without调用它CoroutineScope(Dispatchers.IO).launch {}。请问从建筑设计的角度来看这样的说法正确吗?

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

che*_*e10 8

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

Should I use CoroutineScope(Dispatchers.IO).lauch {} in onMessageRecevied() function?
Run Code Online (Sandbox Code Playgroud)

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

为此你可以做这样的事情

Should I use CoroutineScope(Dispatchers.IO).lauch {} in onMessageRecevied() function?
Run Code Online (Sandbox Code Playgroud)

接下来回答你的第二个问题

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?
Run Code Online (Sandbox Code Playgroud)

我建议您仍然使用 Coroutine Scope,而不是直接使用普通函数,因为无论如何,建议将 Room 与 Coroutine 一起使用,即使从架构的角度来看,也不会造成任何伤害。

第三

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?
Run Code Online (Sandbox Code Playgroud)

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