我正在尝试将所有回调都更改为协程,我已经阅读了有关它们的内容,它们令人着迷!
我要完成的只是登录用户,但是如果登录逻辑失败,则将其通知给我的演示者。
这就是我所做的
class LoginPresenter @Inject constructor(private val signInInteractor: SignInInteractor) : LoginContract.Presenter, CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext = job + Dispatchers.Main
override fun signInWithCoroutines(email: String, password: String) {
launch {
view?.showProgress()
withContext(Dispatchers.IO){
signInInteractor.signInWithCoroutinesTest(email,password)
}
view?.hideProgress()
}
}
}
现在问题出在我的交互器中,因为它具有暂停功能,所以我想返回一个错误响应,以便从演示者那里进行view.showError(errorMsg)
override suspend fun signInWithCoroutinesTest(email: String, password: String) {
FirebaseAuth.getInstance()?.signInWithEmailAndPassword(email, password).addOnCompleteListener {
if(it.isSuccessful){
//Want to notify the presenter that the coroutine has ended succefully
}else{
//want to let the courutine know about it.exception.message.tostring
}
}
}
我这样做的方式是通过通知我的演示者的回调
override fun signInWithCoroutinesTest(email: String, password: String) {
FirebaseAuth.getInstance()?.signInWithEmailAndPassword(email, password,listener:OnSuccessCallback).addOnCompleteListener {
if(it.isSuccessful){
listener.onSuccess()
}else{
listener.onFailure(it.exception.message.toString())
}
}
}
如果从协程成功完成操作并如何通知我的演示者,该如何返回?
谢谢
答案 0 :(得分:1)
您必须明确暂停协程:
userID roleID
1 1
2 1
3 1
1 2
2 2
3 2
1 3
2 3
3 3
此外,由于您的代码可挂起并且不会阻塞,因此请勿运行override suspend fun signInWithCoroutinesTest(
email: String, password: String
) = suspendCancellableCoroutine { continuation ->
FirebaseAuth.getInstance()?.signInWithEmailAndPassword(email, password).addOnCompleteListener {
if (it.isSuccessful) {
continuation.resume(Unit)
} else {
continuation.resumeWithException(it.exception)
}
}
}
。只需直接从主线程中调用它,这就是协程的美丽。
答案 1 :(得分:1)
像常规的同步代码一样思考协程。如果后台工作立即完成,您将如何写?也许是这样的:
override fun signInWithCoroutinesTest(email: String, password: String) {
view?.showProgress()
if(!signInInteractor.signIn(email,password)) view?.showSignInError()
view?.hideProgress()
}
或者,如果您想捕获错误,则类似
override fun signInWithCoroutinesTest(email: String, password: String) {
view?.showProgress()
try {
signInInteractor.signIn(email,password))
} catch(e: AuthenticationException) {
view?.showError(e.message)
}
view?.hideProgress()
}
使用协程,您只需编写完全相同的代码,但方法本身会挂起而不是阻塞线程。因此,在这种情况下,signIn
将是一个暂停函数,需要从协程或其他暂停函数中调用。基于此,您可能希望外部函数挂起,然后启动那个协程,而不是尝试在signInWithCoroutinesTest
内部启动。
原始示例并不完全现实,但是通常您会从现有范围(可能与您的活动或viewModel关联)启动这种事情。最终,它将看起来像这样:
fun hypotheticalLogic() {
...
viewModelScope.launch {
signInWithCoroutinesTest(email, password)
}
...
}
override suspend fun signInWithCoroutinesTest(email: String, password: String) {
view?.showProgress()
try {
signInInteractor.signIn(email,password))
} catch(e: AuthenticationException) {
view?.showError(e.message)
}
view?.hideProgress()
}
关键是想想协程与“常规”顺序代码相同。