我正在使用MVVM设计模式开发一个Android应用程序。
我有一个扩展FirebaseMessagingService
的类FCMService
。
如您所知,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)
}
}
}
我读了一篇stackerflow帖子,发现onMessageReceived()
函数在后台线程中执行,在onMessageReceived(RemoteMessage消息(中完成的所有工作都应该同步完成。
所以,以下是我的问题,
我应该在
onMessageRecevied()
函数中使用CoroutineScope(Dispatchers.IO).lauch {}
吗?如果没有,那么我可以只使用普通函数,而不是挂起存储库中的函数,并且我可以在没有
CoroutineScope(Dispatchers.IO).launch {}
的情况下从onMessageReceived()
调用它。从建筑设计的角度来看,这是正确的吗?这是一个关于Coroutine的问题,但正如你所看到的,我在
FCMService
中通过CoroutineScope(Dispatchers.IO).lauch{ repository.save(remoteMessage) }
在IO线程中启动了一个新的协同程序,但我也在Repository
中通过withContext(Dispatchers.IO) { someDAO.save(removeMessage) }
将协同程序上下文从IO切换到IO。我觉得withContext(Dispatchers.IO) { someDAO.save(removeMessage) }
没有必要,因为我正在从IO切换到IO。我说得对吗?
我会尽力回答。现在来回答您的问题。
Should I use CoroutineScope(Dispatchers.IO).lauch {} in onMessageRecevied() function?
我不认为这有任何问题。Firebase消息服务基本上仍然是一项服务,因此应该不会有任何问题。我建议您创建一个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?
我建议您仍然使用您的Coroutine Scope,而不是直接使用普通函数,因为无论怎样,都建议使用带有Coroutines的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)
,只是为了与您的其他结构保持一致。