如何 return 来自协程的错误响应
How to return error responses from Coroutines
我正在尝试将我所有的回调更改为协程,我已经阅读了它们并且它们很吸引人!
我想完成的只是登录一个用户,但如果登录逻辑失败,通知我的演示者。
这是我做的
LoginPresenter.kt
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()
}
}
}
现在问题出在我的交互器上,因为它是一个挂起函数,我很想 return 一个错误响应,以便从我的演示者
那里做一个 view.showError(errorMsg)
SignInInteractor.kt
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())
}
}
}
问题
如何return如果协程操作成功并通知我的演示者?
谢谢
您必须明确暂停协程:
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)
}
}
}
此外,由于您的代码是可挂起的并且不会阻塞,所以不要 运行 它 withContext(IO)
。直接在主线程中调用即可,这就是协程的美妙之处。
将协程视为正常的同步代码。如果后台工作立即完成,你会怎么写?也许是这样的:
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
将是一个挂起函数,需要从协程或其他挂起函数中调用。基于此,您可能希望暂停外部函数,然后启动 that 协同程序,而不是尝试在 signInWithCoroutinesTest
.
内部启动
原始示例并不完全符合实际,但通常您会从现有范围启动此类内容,可能与您的 activity 或 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()
}
关键是要将协同程序视为与 "normal" 顺序代码相同的方式。
我正在尝试将我所有的回调更改为协程,我已经阅读了它们并且它们很吸引人!
我想完成的只是登录一个用户,但如果登录逻辑失败,通知我的演示者。
这是我做的
LoginPresenter.kt
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()
}
}
}
现在问题出在我的交互器上,因为它是一个挂起函数,我很想 return 一个错误响应,以便从我的演示者
那里做一个view.showError(errorMsg)
SignInInteractor.kt
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())
}
}
}
问题
如何return如果协程操作成功并通知我的演示者?
谢谢
您必须明确暂停协程:
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)
}
}
}
此外,由于您的代码是可挂起的并且不会阻塞,所以不要 运行 它 withContext(IO)
。直接在主线程中调用即可,这就是协程的美妙之处。
将协程视为正常的同步代码。如果后台工作立即完成,你会怎么写?也许是这样的:
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
将是一个挂起函数,需要从协程或其他挂起函数中调用。基于此,您可能希望暂停外部函数,然后启动 that 协同程序,而不是尝试在 signInWithCoroutinesTest
.
原始示例并不完全符合实际,但通常您会从现有范围启动此类内容,可能与您的 activity 或 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()
}
关键是要将协同程序视为与 "normal" 顺序代码相同的方式。