协程中的代码块使用 "Dispatchers.Main" 而不是 运行
Code block in coroutine using "Dispatchers.Main" not being run
我到处搜索,但没有找到任何似乎可以解决我的问题的方法
我有一个使用协程的函数:
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。
我有点沮丧,我不确定我是否不明白 dispatcher/coroutine 应该如何工作,或者我缺少什么。
如果您需要任何其他详细信息或代码,请告诉我!
编辑
所以马尔科是对的。在我移动 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 帮助我!
activity?.setResult(Activity.RESULT_OK, Intent())
在这里您尝试从 IO 线程访问 GUI 组件。这可能会抛出一个异常,但由于它在 IO 线程上,所以没有任何东西捕获它。
您可以将所有内容包装在 try-catch 中,但如果您使用正确的习惯用法,即在 Main
调度程序中 launch
并且仅切换,您的程序会自动运行得更好到阻塞操作的 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 调度程序中遇到异常,它将传播到 top-level 协程,这将导致主线程发生异常,您的应用程序将随之崩溃。这是在其上添加错误处理逻辑的坚实基础。
当然,这仍然不是您应该使用协程的方式,因为您缺少结构化并发方面。
我到处搜索,但没有找到任何似乎可以解决我的问题的方法
我有一个使用协程的函数:
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。
我有点沮丧,我不确定我是否不明白 dispatcher/coroutine 应该如何工作,或者我缺少什么。
如果您需要任何其他详细信息或代码,请告诉我!
编辑
所以马尔科是对的。在我移动 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 帮助我!
activity?.setResult(Activity.RESULT_OK, Intent())
在这里您尝试从 IO 线程访问 GUI 组件。这可能会抛出一个异常,但由于它在 IO 线程上,所以没有任何东西捕获它。
您可以将所有内容包装在 try-catch 中,但如果您使用正确的习惯用法,即在 Main
调度程序中 launch
并且仅切换,您的程序会自动运行得更好到阻塞操作的 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 调度程序中遇到异常,它将传播到 top-level 协程,这将导致主线程发生异常,您的应用程序将随之崩溃。这是在其上添加错误处理逻辑的坚实基础。
当然,这仍然不是您应该使用协程的方式,因为您缺少结构化并发方面。