#android #kotlin #android-jetpack-compose #android-jetpack-navigation
Вопрос:
У меня есть экран входа в систему, и когда вход в систему будет успешным, а модель представления обновит переменную изменяемого состояния, я ожидаю, что будет вызвана новая составная функция для отображения нового экрана, а вход в систему будет удален. Проблема в том, что при отображении нового экрана (он же Screen.AccountsScreen
) его содержимое продолжает мигать/перерисовываться, и то же самое происходит с формой входа в систему, которая никогда не уничтожается (я знаю это, потому что сообщение журнала «Переназначение…» печатается бесконечно). Я предполагаю, что это происходит, потому isLoginSuccessful
что состояние всегда истинно. Кажется, мне нужно событие, которое можно использовать только один раз, это правильно? Если да, то как я могу это сделать?
LoginViewModel.kt
@HiltViewModel
class LoginViewModel @Inject constructor() : ViewModel() {
var isLoginSuccessful by mutableStateOf(false)
var errorMessage by mutableStateOf("")
fun onLoginClick(email: String, password:String) {
errorMessage = ""
if (credentialsValid(email, password)) {
isLoginSuccessful = true
} else {
errorMessage = "Email or password invalid"
isLoginSuccessful = false
}
}
}
LoginScreen.kt
@Composable
fun loginScreen(
navController: NavController,
viewModel: LoginViewModel = hiltViewModel()
) {
println("Recomponing...")
// Here gos the code for the login form
if (viewModel.isLoginSuccessful) {
navController.navigate(Screen.AccountsScreen.route) {
popUpTo(Screen.LoginScreen.route) { inclusive = true }
}
}
}
Комментарии:
1. Привет! Мой ответ решил ваш вопрос? Если да, пожалуйста, примите это, поставив галочку под счетчиком голосов. В противном случае, дайте мне знать, если у вас возникнут какие-либо проблемы с этим.
Ответ №1:
Составная навигация перестраивает как исчезающие, так и появляющиеся представления во время перехода. Это ожидаемое поведение.
Вы вызываете навигацию при каждой перестановке. Ваша проблема заключается в этих строках:
if (viewModel.isLoginSuccessful) {
navController.navigate(Screen.AccountsScreen.route) {
popUpTo(Screen.LoginScreen.route) { inclusive = true }
}
}
Вы не должны изменять состояние непосредственно из конструкторов представлений. В этом случае LaunchedEffect
следует использовать:
if (viewModel.isLoginSuccessful) {
LaunchedEffect(Unit) {
navController.navigate(Screen.AccountsScreen.route) {
popUpTo(Screen.LoginScreen.route) { inclusive = true }
}
}
}
Ознакомьтесь с дополнительной документацией по побочным эффектам.