协程中使用“ Dispatchers.Main”的代码块未运行

时间:2019-05-13 03:07:15

标签: android kotlin kotlin-coroutines

我到处搜索,但找不到任何可以解决我问题的方法

我有一个使用协程的函数:

fun onAuthenticated() {
    launch (Dispatchers.IO) {
        userRepo.retrieveSelf()!!.let { name ->
            userRepo.addAuthenticatedAccount(name)
            userRepo.setCurrentAccount(name)
        }

        activity?.setResult(Activity.RESULT_OK, Intent())

        // this block doesn't seem to be run
        withContext(Dispatchers.Main) {
            Log.d(TAG, "ok looks gucci")
            activity?.finish()
        }
    }
}

调用此函数时,withContext(Dispatchers.Main) { ... }块中的代码不运行。我正在用它来访问主线程中的活动。

我一直感到沮丧,我不确定是否不知道调度员/协程应该如何工作,或者我缺少什么。

让我知道您是否需要其他详细信息或代码!

EDIT 所以Marko是对的。在移动activity.?.setResult(Activity.RESULT_OK, Intent())使其与主调度程序一起运行之后,我发现userRepo.setCurrentAccount(name)中的另一部分代码出现了问题。如下所示更新代码后,它可以按预期工作!

override fun onAuthenticated() {
    val handler = CoroutineExceptionHandler { _, e ->
        Snackbar.make(
            web_auth_rootview,
                "Authentication unsuccessful",
                Snackbar.LENGTH_INDEFINITE
            ).show()
    }

    launch(Dispatchers.Main + handler) {
        userRepo.retrieveSelf()!!.let { name ->
            userRepo.addAuthenticatedAccount(name)
            userRepo.setCurrentAccount(name)
        }

        activity?.apply {
            setResult(Activity.RESULT_OK, Intent())
            onBackPressed()
        }
    }
}      

非常感谢Marko帮助我!

1 个答案:

答案 0 :(得分:1)

activity?.setResult(Activity.RESULT_OK, Intent())

在这里,您尝试从IO线程接触GUI组件。这可能会引发异常,但是由于它在IO线程上,因此没有任何异常。

您可以将所有内容包装在try-catch中,但是如果您使用适当的习惯用法,则程序将自动运行得更好,该习惯用法是在launch调度程序中进行Main的操作,并且仅切换到IO上下文用于阻止操作:

launch(Dispatchers.Main) {
    withContext(Dispatchers.IO) {
        userRepo.retrieveSelf()!!.let { name ->
            userRepo.addAuthenticatedAccount(name)
            userRepo.setCurrentAccount(name)
        }
    }
    activity?.setResult(Activity.RESULT_OK, Intent())
    Log.d(TAG, "ok looks gucci")
    activity?.finish()
}

现在,如果在IO调度程序中收到异常,它将传播到顶级协程,这将在主线程上引起异常,并且应用程序将因此崩溃。这是在上面添加错误处理逻辑的坚实基础。

当然,由于您缺少结构化并发方面,因此仍然不是应使用协程的方式。