android - 使用协程冻结 UI 的 Firebase 身份验证
问题描述
我正在尝试使用 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
}
}
}
}
}
解决方案
发现一个问题,这是因为我将 toastMessage 设置为 null 然后在登录片段中观察它,不知何故它冻结了我的 UI,将其删除修复了所有问题。
推荐阅读
- java - 尝试使用 KeyboardFocusManager 查找当前聚焦的窗口总是会导致错误消息
- c++ - 使用#include 找不到文件错误错误
- javascript - Javascript .multiply'找不到函数'
- flutter - 未处理的异常:NoSuchMethodError:在 null 上调用了方法“[]”。尝试调用:[]("username")
- image-segmentation - 在 Canny 边缘检测中应用自适应阈值
- python - 如何测试字符串是否包含列表中的所有子字符串:pandas?
- r - DCA:使用自动绘图或 ggplot2 标记点
- flutter - Flutter 中的嵌套流构建器和快照
- node.js - Ubuntu 上的 `npm link` 注册命令在哪里?
- javascript - 命令失败时的Javascript