1

I have a main composable that wraps a NavHost to display different screens. Some of these screens need to navigate to other screens based on state changes in a ViewModel that happen as a result of method calls. Here's a trimmed down example of what I have at the moment:

class ExampleViewModel(application: Application) : AndroidViewModel(application) {
  // Used by a
  var error: String? by mutableStateOf(null)
    private set

  var user: User? by mutableStateOf(null)
    private set

  fun onLogin(email: String, password: String) {
    viewModelScope.launch {
      doLogin(email, password)
        .onSuccess { user = it }
        .onFailure { error = it.localizedMessage }
    }
  }
}

@Composable
fun LoginScreen(
  navController: NavController,
  exampleViewModel: ExampleViewModel,
) {
  DisposableEffect(exampleViewModel.user) {
    if (exampleViewModel.user != null) {
      navController.navigate("somewhere")
    }
    onDispose {}
  }

  var email by rememberSaveable { mutableStateOf("") }
  var password by rememberSaveable { mutableStateOf("") }

  // Email TextField.
  // Password TextField.
  Button(onClick = { exampleViewModel.onLogin(email, password) }) {
    Text("Login")
  }
}

The error is handled like this in a composable up above:

LaunchedEffect(exampleViewModel.error) {
  exampleViewModel.error?.let { scaffoldState.snackbarHostState.showSnackbar(it) }
}

Using a DisposableEffect in this way seems kind of dirty, and quite error prone. On top of that, this error handling method makes it difficult to, for example, disable the login form while the login is pending. Would it be better to make onLogin() suspend and handle its success and failures, and corresponding local state, in a callback inside of LoginScreen? The downside to that is that the login screen will no longer automatically redirect if it's navigated to while already logged in. snapshotFlow in a LaunchedEffect(true) is another thing I've considered, but that doesn't really seem to have any particular benefits over DisposableEffect.

What's the correct way to do this? Am I on completely the wrong track here?

DeedleFake
  • 11
  • 3
  • Could you check if this answer helps you? https://stackoverflow.com/questions/68044251/stateflow-observer-is-being-triggered-two-times-is-this-a-good-solution/68061641#68061641 – nglauber Jul 24 '21 at 03:37

0 Answers0