android - Kotlin Coroutines - 嵌套协程是在一个协程中处理不同线程的正确方法吗?

标签 android kotlin kotlin-coroutines

我第一次在基本网络调用上尝试使用协程而不是 RxJava,看看它是什么样的,并遇到了一些滞后/线程问题

在下面的代码中,我正在执行网络调用 userRepo.Login(),如果发生异常,我会显示一条错误消息并停止我在开始时启动的进度动画功能。

如果我将所有内容都留在 CommonPool 上(或不添加任何池),它会崩溃,并指出如果发生异常,动画必须在循环线程上完成。在其他情况下,我收到错误消息说这也必须在 UI 线程上完成,同样的问题,不同的线程要求。

不过,我无法在 UI 线程上启动整个协程,因为登录调用会阻塞,因为它在 UI 线程上并且会弄乱我的动画(这是有道理的)。

我认为解决这个问题的唯一方法是从现有协程中在 UI 线程上启动一个新协程,这可行,但看起来很奇怪。

这是正确的做事方式,还是我遗漏了什么?

override fun loginButtonPressed(email: String, password: String) {

    view.showSignInProgressAnimation()

    launch(CommonPool) {
        try { 
            val user = userRepo.login(email, password)

            if (user != null) {
                view.launchMainActivity()
            }

        } catch (exception: AuthException) {
            launch(UI) {
                view.showErrorMessage(exception.message, exception.code)
                view.stopSignInProgressAnimation()
            }
        }
    }
}

最佳答案

您应该从相反的一端开始:启动一个基于 UI 的协程,您可以从中将繁重的操作移交给外部池。选择的工具是 withContext():

override fun loginButtonPressed(email: String, password: String) {
    view.showSignInProgressAnimation()
    // assuming `this` is a CoroutineScope with dispatcher = Main...
    this.launch {
        try {
            val user = withContext(IO) { 
                userRepo.login(email, password) 
            }
            if (user != null) {
                view.launchMainActivity()
            }
        } catch (exception: AuthException) {
            view.showErrorMessage(exception.message, exception.code)
            view.stopSignInProgressAnimation()
        }
    }
}

这样您就可以保持自然的 Android 编程模型,该模型采用 GUI 线程。

关于android - Kotlin Coroutines - 嵌套协程是在一个协程中处理不同线程的正确方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50165202/

相关文章:

android - 使用协程 api 获取实体

android - Probleme线程连接数据库mysql android

java - 运行 Roboelectric 单元测试时出现 NoClassDefFoundError

android - RecyclerView : Inconsistency detected when update grouped items by PagedListAdapter

kotlin - 在 Kotlin 中打印 0001 到 1000。如何为数字添加填充?

android - 在Android Kotlin协程中尝试/捕获导致崩溃

android - 错误:找不到符号变量relativeLayout

android - 文本可组合尺寸资源不能用作 fontSize 参数

android - Gson会忽略序列化时枚举的自定义@SerializedName值

kotlin - 如何在kotlin中编写包含mutex.withLock的getter和setter