首页 > 解决方案 > 协同程序中使用“Dispatchers.Main”的代码块未运行

问题描述

我到处搜索,但没有找到任何似乎可以解决我的问题的方法

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

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) { ... }块中的代码不会运行。我正在使用它来访问主线程中的活动。

我有点沮丧,我不确定我是否不明白调度程序/协程应该如何工作,或者我缺少什么。

如果您需要任何其他详细信息或代码,请告诉我!

编辑 所以马尔科是对的。在我移动它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 帮助我!

标签: androidkotlinkotlin-coroutines

解决方案


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

在这里,您尝试从 IO 线程中触摸一个 GUI 组件。这可能会引发异常,但由于它位于 IO 线程上,因此没有任何东西可以捕获它。

您可以将所有内容包装在 try-catch 中,但如果您使用正确的习惯用法,您的程序会自动运行得更好,即launchMain调度程序中,并且只切换到阻塞操作的 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 调度程序中遇到异常,它将传播到顶级协程,这将导致主线程上的异常,并且您的应用程序将随之崩溃。这是在其上添加错误处理逻辑的坚实基础。

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


推荐阅读