首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解coroutineScope

理解coroutineScope
EN

Stack Overflow用户
提问于 2020-06-27 10:01:47
回答 1查看 838关注 0票数 1

假设在VM中使用viewModelScope启动了一个新的协同器,并在泛型存储库类中调用了一个非挂起函数。

UserViewModel

代码语言:javascript
复制
viewModelScope.launch(context = Dispatchers.IO) {

                _user.value?.id?.let { id ->
                    val dataSaved = userRepository.setUserData(id, newUser)

                }

}

UserRepository

代码语言:javascript
复制
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
        }
}

  1. 启动setUserData的作用域和上下文是什么?
  2. 如果在setUserData函数之前添加suspend关键字,Tasksawait方法将生成一个警告:Inappropriate blocking method call。为什么? implementation?

  • 有什么区别?

代码语言:javascript
复制
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
            }
        }
  }

  1. coroutineScope是在调用方

的相同范围和上下文内启动setUserData的保证。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-27 15:09:09

启动setUserData的范围和上下文是什么?

viewModelScope.launch(context = Dispatchers.IO)判断,上下文看起来是CoroutineScope(SupervisorJob() + Dispatchers.IO)

--如果我在setUserData函数之前添加suspend关键字,那么Tasksawait方法将生成一个警告,上面写着Inappropriate blocking method call。为什么?

在挂起函数中阻塞线程(使用Tasks.await)是错误的做法,除非dispatcher支持这一点。即Dispatchers.IO.

IntelliJ/Android不够聪明(而且可能不可能),无法精确确定在不应该阻塞的情况下是否阻塞。所以这可以被认为是一个bug,但是setUserData可以在Dispatchers.IO之外被调用,所以IntelliJ在这里有一个观点。

这个实现有什么区别?

不算什么。它只是有一些额外的开销是不值得的。

顺便提一句,coroutineScope并不像withContext那样改变即时的coroutineContext,但是它改变了已启动协同的继承上下文。

coroutineScope在调用者的相同范围和上下文内启动setUserData的保证吗?

你已经得到这个保证了。您不需要coroutineScope来实现这一点。

你可能想要的是这个。

代码语言:javascript
复制
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
        }
    }
}

然后调用方不必担心要使用什么调度程序或上下文。

你应该用的是这个。

代码语言:javascript
复制
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://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-play-services/kotlinx.coroutines.tasks/com.google.android.gms.tasks.-task/await.html

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62608541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档