假设在VM中使用viewModelScope启动了一个新的协同器,并在泛型存储库类中调用了一个非挂起函数。
UserViewModel
viewModelScope.launch(context = Dispatchers.IO) {
_user.value?.id?.let { id ->
val dataSaved = userRepository.setUserData(id, newUser)
}
}UserRepository
fun setUserData(id: String, data: User): Boolean {
return try {
val saveTask = db.collection(COLLECTION).document(id).set(data)
Tasks.await(saveTask)
true
} catch (e: Throwable) {
false
}
}setUserData的作用域和上下文是什么?setUserData函数之前添加suspend关键字,Tasks的await方法将生成一个警告:Inappropriate blocking method call。为什么? implementation?和
suspend fun setUserData(id: String, data: User): Boolean {
return coroutineScope {
return@coroutineScope try {
val saveTask = db.collection(COLLECTION).document(id).set(data)
Tasks.await(saveTask)
true
} catch (e: Throwable) {
e.printStackTrace()
Log.e(TAG, "${e.message}")
false
}
}
}coroutineScope是在调用方的相同范围和上下文内启动setUserData的保证。
发布于 2020-06-27 15:09:09
启动
setUserData的范围和上下文是什么?
从viewModelScope.launch(context = Dispatchers.IO)判断,上下文看起来是CoroutineScope(SupervisorJob() + Dispatchers.IO)。
--如果我在
setUserData函数之前添加suspend关键字,那么Tasks的await方法将生成一个警告,上面写着Inappropriate blocking method call。为什么?
在挂起函数中阻塞线程(使用Tasks.await)是错误的做法,除非dispatcher支持这一点。即Dispatchers.IO.
IntelliJ/Android不够聪明(而且可能不可能),无法精确确定在不应该阻塞的情况下是否阻塞。所以这可以被认为是一个bug,但是setUserData可以在Dispatchers.IO之外被调用,所以IntelliJ在这里有一个观点。
这个实现有什么区别?
不算什么。它只是有一些额外的开销是不值得的。
顺便提一句,coroutineScope并不像withContext那样改变即时的coroutineContext,但是它改变了已启动协同的继承上下文。
是
coroutineScope在调用者的相同范围和上下文内启动setUserData的保证吗?
你已经得到这个保证了。您不需要coroutineScope来实现这一点。
你可能想要的是这个。
suspend fun setUserData(id: String, data: User): Boolean {
val saveTask = db.collection(COLLECTION).document(id).set(data)
return withContext(Dispatchers.IO) {
try {
Tasks.await(saveTask)
true
} catch (e: Throwable) {
e.printStackTrace()
Log.e(TAG, "${e.message}")
false
}
}
}然后调用方不必担心要使用什么调度程序或上下文。
你应该用的是这个。
suspend fun setUserData(id: String, data: User): Boolean {
val saveTask = db.collection(COLLECTION).document(id).set(data)
return try {
saveTask.await() // From `kotlinx-coroutines-play-services`
true
} catch (e: Throwable) {
e.printStackTrace()
Log.e(TAG, "${e.message}")
false
}
}这样,您就不需要调用Dispatchers.IO并阻塞更多线程。
https://stackoverflow.com/questions/62608541
复制相似问题