Kotlin Coroutines - 嵌套协程是在一个协程中处理不同线程的正确方法吗?
Kotlin Coroutines - Are nested coroutines the proper way to handle different threading within one coroutine?
我第一次在基本网络调用上尝试使用协同程序而不是 RxJava 来了解它是什么样的,运行 解决 lag/threading
的一些问题
在下面的代码中,我正在执行网络调用 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 线程。
我第一次在基本网络调用上尝试使用协同程序而不是 RxJava 来了解它是什么样的,运行 解决 lag/threading
的一些问题在下面的代码中,我正在执行网络调用 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 线程。