我尝试在基本网络呼叫上尝试协程而不是RxJava,以便了解它的含义并遇到滞后/线程的某些问题
在下面的代码中,我正在进行网络调用userRepo.Login()
,如果发生异常,我会显示错误消息并停止我在函数开始时启动的进度动画。
如果我将所有内容保留在CommonPool上(或者不添加任何池),它会崩溃,如果发生异常,则必须在looper线程上完成动画。在其他情况下,我收到错误,说这必须在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()
}
}
}
}
答案 0 :(得分:5)
你应该从另一端开始:启动一个基于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线程。