[英]How to fix android based Firebase error while deleting objects causing an infinite loop?
[英]How to resolve infinite loop causing by state change in android compose with firebase authentication
我有一个应用程序,通过 email 登录,密码为 firebase。 我正在使用带有 MVVM 和干净架构的 jetpack compose。
当从 firebase 获取登录已完成时,我在视图 model 中得到了正确的结果,然后在可组合物中收听此 state 更改。
问题是我总是在 state 中出现符号的 when 语句,它会导致一个无限循环,总是导航到下一个可组合。
在此处复制视图中的特定行:
when (val response = viewModel.signInState.value) {
is Response.Loading -> LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
is Response.Success -> if (response.data) {
navController?.navigate(Screen.HomeScreen.route)
}
is Response.Error -> LaunchedEffect(Unit) {
scaffoldState.snackbarHostState.showSnackbar("Error signing out. ${response.message}", "", SnackbarDuration.Short)
}
}
我的观点:
@Composable
fun LoginScreen(
navController: NavController?,
viewModel: LoginViewModel = hiltViewModel()
) {
val scaffoldState = rememberScaffoldState()
Scaffold(scaffoldState = scaffoldState) {
Column (
modifier = Modifier
.fillMaxHeight()
.background(
Color.White
),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
){
var email = viewModel.email
var pass = viewModel.password
var passwordVisibility = viewModel.passwordVisibility
TitleView(title = "SIGN IN", topImage = Icons.Filled.Person, modifier = Modifier)
Spacer(modifier = Modifier.padding(20.dp))
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
value = email.value,
onValueChange = viewModel::setEmail,
label = { Text( "Email")},
placeholder = { Text("Password") }
)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
value = pass.value,
onValueChange = viewModel::setPassword,
label = { Text( "Password")},
placeholder = { Text("Password") },
visualTransformation = if (passwordVisibility.value) VisualTransformation.None else PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
trailingIcon = {
val image = if (passwordVisibility.value)
Icons.Filled.Visibility
else Icons.Filled.VisibilityOff
IconButton(onClick = {
viewModel.setPasswordVisibility(!passwordVisibility.value)
}) {
Icon(imageVector = image, "")
}
}
)
Spacer(modifier = Modifier.padding(5.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.border(
width = 2.dp,
brush = SolidColor(Color.Yellow),
shape = RoundedCornerShape(size = 10.dp)
),
onClick = {
viewModel.signInWithEmailAndPassword()
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.White
)
) {
Text(
text = "SIGN IN",
textAlign = TextAlign.Center,
fontSize = 20.sp,
style = TextStyle(
fontWeight = FontWeight.Thin
)
)
}
Spacer(modifier = Modifier.padding(5.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.border(
width = 2.dp,
brush = SolidColor(Color.Yellow),
shape = RoundedCornerShape(size = 10.dp)
),
onClick = {
viewModel.forgotPassword()
},
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.White
)
) {
Text(
text = "FORGOT PASSWORD",
textAlign = TextAlign.Center,
fontSize = 20.sp,
style = TextStyle(
fontWeight = FontWeight.Thin
)
)
}
}
}
}
when (val response = viewModel.signInState.value) {
is Response.Loading -> LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
is Response.Success -> if (response.data) {
navController?.navigate(Screen.HomeScreen.route)
}
is Response.Error -> LaunchedEffect(Unit) {
scaffoldState.snackbarHostState.showSnackbar("Error signing out. ${response.message}", "", SnackbarDuration.Short)
}
}
when (val response = viewModel.forgotState.value) {
is Response.Loading -> LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
is Response.Success -> if (response.data) {
LaunchedEffect(Unit){
scaffoldState.snackbarHostState.showSnackbar("Please click the link in the verification email sent to you", "", SnackbarDuration.Short)
}
}
is Response.Error -> LaunchedEffect(Unit){
scaffoldState.snackbarHostState.showSnackbar("Error signing out. ${response.message}", "", SnackbarDuration.Short)
}
}
}
我的看法 model:
@HiltViewModel
class LoginViewModel @Inject constructor(
private val useCases: UseCases
) : ViewModel() {
private val _signInState = mutableStateOf<Response<Boolean>>(Response.Success(false))
val signInState: State<Response<Boolean>> = _signInState
private val _forgotState = mutableStateOf<Response<Boolean>>(Response.Success(false))
val forgotState: State<Response<Boolean>> = _forgotState
private val _email = mutableStateOf("")
val email = _email
fun setEmail(email: String) {
_email.value = email
}
private val _password = mutableStateOf("")
val password = _password
fun setPassword(password: String) {
_password.value = password
}
private val _passwordVisibility = mutableStateOf(false)
val passwordVisibility = _passwordVisibility
fun setPasswordVisibility(passwordVisibility: Boolean) {
_passwordVisibility.value = passwordVisibility
}
fun signInWithEmailAndPassword() {
viewModelScope.launch {
useCases.signInWithEmailAndPassword(_email.value, _password.value).collect { response ->
_signInState.value = response
}
}
}
fun forgotPassword() {
viewModelScope.launch {
useCases.forgotPassword(_email.value).collect { response ->
_forgotState.value = response
}
}
}
}
我的登录 function:
override suspend fun signInWithEmailAndPassword(
email: String,
password: String
) = flow {
try {
emit(Response.Loading)
val result = auth.signInWithEmailAndPassword(email, password).await()
if (result.user != null)
emit(Response.Success(true))
else
emit(Response.Success(false))
} catch (e: Exception) {
emit(Response.Error(e.message ?: ERROR_MESSAGE))
}
}
导航也是一个副作用,在 animation 的每一帧之后,您将再次导航到您的目的地。 将您的块更改为:
when (val response = viewModel.signInState.value) {
is Response.Loading -> LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
is Response.Success -> if (response.data) LaunchedEffect(response.data){ navController?.navigate(Screen.HomeScreen.route) }
is Response.Error -> LaunchedEffect(Unit) {
scaffoldState.snackbarHostState.showSnackbar("Error signing out. ${response.message}", "", SnackbarDuration.Short)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.