【发布时间】:2021-05-10 15:49:44
【问题描述】:
我正在尝试使用 Firebase 身份验证、协程和 MVVM 模式为我的应用程序执行登录功能。关键是身份验证只有在成功时才会给我回调,否则它会冻结整个应用程序,我不知道为什么。我对android编程很陌生,我依赖互联网上的项目,我的代码可能很乱。这是我的代码:
Firebase 存储库:
class UserRepositoryImpl : UserRepository {
private val authentication: FirebaseAuth by lazy {
FirebaseAuth.getInstance()
}
override suspend fun firebaseLoginUser(email: String, password: String): Result<FirebaseUser?> {
try{
return when(val authResult = authentication.signInWithEmailAndPassword(email, password).await())
{
is Result.Success<*> -> {
val firebaseUser = authentication.currentUser
Result.Success(firebaseUser)
}
is Result.Error -> {
Result.Error(authResult.exception)
}
is Result.Canceled ->{
Result.Canceled(authResult.exception)
}
else -> throw UnsupportedOperationException()
}
}
catch (e: Exception){
return Result.Error(e)
}
}
认证回调类:
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
data class Canceled(val exception: Exception?) : Result<Nothing>()
}
自定义Task.await()方法:
suspend fun <T> Task<T>.await(): Result<T>
{
if (isComplete)
{
val e = exception
return if (e == null)
{
if (isCanceled){
Result.Canceled(CancellationException("Task $this was cancelled"))}
else {
@Suppress("UNCHECKED_CAST")
Result.Success(result as T)}
}
else {
Result.Error(e) }
}
return suspendCancellableCoroutine { cont ->
addOnCompleteListener {
val e = exception
if (e == null)
{
@Suppress("UNCHECKED_CAST")
if (isCanceled) {
cont.cancel() }
else {
cont.resume(Result.Success(result as T)) }
}
else {
cont.resumeWithException(e) }
}
}
}
视图模型:
class AuthenticationViewModel(
private val repository: UserRepositoryImpl
) : ViewModel() {
//Databinding values
var email: String? = null
var password: String? = null
private val _toastMessage = MutableLiveData<Any?>()
val toastMessage: LiveData<Any?>
get() = _toastMessage
fun login() {
if (email.isNullOrEmpty() || password.isNullOrEmpty()) {
_toastMessage.value = R.string.login_noCredentials
return
}
else{
viewModelScope.launch {
when (val result = repository.firebaseLoginUser(email!!, password!!)) {
is Result.Success -> {
// app.startHomeActivity()
}
}
is Result.Error -> {
_toastMessage.value = result.exception.message
}
is Result.Canceled -> {
_toastMessage.value = R.string.login_canceled
}
}
}
}
}
【问题讨论】:
-
您不必重新发明轮子。 kotlin.github.io/kotlinx.coroutines/…
-
我在网上关注示例项目,是这样完成的,实际上我没有尝试过基本的协程方法,将尝试
-
不过,您的自定义实现似乎还不错。我在代码中看到的一个问题是,您应该在通过
startHomeActivity()显式登录后让应用程序继续运行,但是当登录失败时您只显示祝酒词。所以 GUI 并不是字面上“冻结”的,只是什么都没有发生。
标签: android firebase-authentication kotlin-coroutines