Warum blinkt die Ansicht bei Verwendung der Jetpack-Navigation mit Compose?

Lesezeit: 2 Minuten

Benutzer-Avatar
Androider2

Ich habe einen Anmeldebildschirm, und wenn die Anmeldung erfolgreich ist und das Ansichtsmodell die veränderliche Zustandsvariable aktualisiert, erwarte ich, dass eine neue zusammensetzbare Funktion aufgerufen wird, um einen neuen Bildschirm anzuzeigen, und der Anmeldebildschirm wird entfernt. Das Problem ist, dass wenn der neue Bildschirm (aka Screen.AccountsScreen) angezeigt, sein Inhalt blinkt/neu gezeichnet und dasselbe passiert mit dem Login-Formular, das nie zerstört wird (ich weiß das, weil die Log-Meldung ‘Recomponing…’ endlos gedruckt wird). Ich nehme an, dass dies geschieht, weil die isLoginSuccessful Zustand ist immer wahr. Anscheinend brauche ich ein Ereignis, das nur einmal konsumiert werden kann, ist das richtig? Wenn ja, wie kann ich das tun?

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 }
    }
  }
}

  • Hi! Konnte meine Antwort Ihre Frage lösen? Wenn ja, akzeptieren Sie dies bitte mit einem Häkchen unter dem Stimmenzähler. Ansonsten lassen Sie mich wissen, wenn Sie irgendwelche Probleme damit haben.

    – Pylyp Dukhov

    18. Oktober 2021 um 16:11 Uhr

  • @Pylyp Dukhov Meine Bildschirme blinken auch manchmal und ich habe den Grund noch nicht herausgefunden. In meinem Fall geschieht die Aktion zum Navigieren in einem Lambda auf Knopfdruck. Afaik Ich muss in diesem Fall keinen Launched-Effekt verwenden, da das Lambda nicht Teil der Komposition ist, aber wenn es passiert, geht der Zustand meiner Komposition verloren und ich erhalte einen Bildschirmblitz. nicht sicher, was ich vermisse

    – quealegriamasalegre

    1. April um 19:30 Uhr

  • @quealegriamasalegre Es ist schwer zu sagen, bitte reduzieren Sie Ihren Code auf ein minimales reproduzierbares Beispiel und stellen Sie eine andere Frage, da es anscheinend nicht mit dieser zusammenhängt.

    – Pylyp Dukhov

    2. April um 1:28

  • Die Sache ist, dass ich es nicht konsequent reproduzieren kann. Ich werde versuchen, die Bedingungen dafür zu schaffen, dass dies konsequent geschieht, und die Frage dann posten

    – quealegriamasalegre

    2. April um 15:02 Uhr

Benutzer-Avatar
Pylyp Dukhov

Die zusammengesetzte Navigation setzt während des Übergangs sowohl verschwindende als auch erscheinende Ansichten neu zusammen. Dies ist das erwartete Verhalten.

Sie rufen Navigieren bei jeder Neuzusammenstellung auf. Dein Problem liegt in diesen Zeilen:

if (viewModel.isLoginSuccessful) {
    navController.navigate(Screen.AccountsScreen.route) {
        popUpTo(Screen.LoginScreen.route) { inclusive = true }
    }
}

Sie sollten den Status nicht direkt von View Buildern aus ändern. In diesem Fall LaunchedEffect sollte benutzt werden:

if (viewModel.isLoginSuccessful) {
    LaunchedEffect(Unit) {
        navController.navigate(Screen.AccountsScreen.route) {
            popUpTo(Screen.LoginScreen.route) { inclusive = true }
        }
    }
}

Weitere Informationen finden Sie unter Nebenwirkungen Dokumentation.

1010940cookie-checkWarum blinkt die Ansicht bei Verwendung der Jetpack-Navigation mit Compose?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy