Now that I'm trying to convert from my own navigat...
# compose
a
Now that I'm trying to convert from my own navigation code (based on https://github.com/android/compose-samples/blob/main/JetNews/app/src/main/java/com/example/jetnews/ui/Navigation.kt), to navigation-compose. I'm finding all these navigate() calls to be somewhat non-declarative. Anyone else feel this way?
r
Yes, but I think it's good that way. I like that it's clear, easy to understand code, which would not be the case if they went for a functional programming purity test. SwiftUI's "NavigationLink" is more declarative and I find it harder to understand.
1
a
Well, I don't like NavigationLink either. That's a non-view that is on the view tree for some reason. Maybe it's the untouchable backstack that it causing me all this pain. I just want to manipulate the backstack freely in some cases, for example when doing conditional navigation. Is it possible to link a mutableState to a navigate() call? Like if a state
userAuthenticated
becomes false, can I navigate to screen A immediately?
r
Mmm. It seems we can't attach listeners to MutableState, but it's just an interface, so could we implement a version that allows attaching listeners? By Kotlin/Java rules, yes - but I suspect it won't work with Compose.
a
I figured out a way, not sure if this is the best way but this works. This is right after the nav graph is created. Does look very declarative though. This is for an app like a password manager where switching away from the app should deauthenticate the user so they have to enter the password again, and the backstack should also behave accordingly.
Copy code
/**
     * If not authenticated, navigate to Password screen.
     * [MainActivity.onBackPressed] controls closing the app
     * when back button is pressed.
     * When authenticated, if the user wasn't already in the app,
     * show the Home screen, otherwise pop the backstack to resume
     * what the user was doing.
     */
val authenticated by authVm.authState.observeAsState(initial = AuthState.Unauthenticated)
    onCommit(authenticated) {
        Timber.d("Authenticated: $authenticated")
        if (authenticated != AuthState.Authenticated) {
            navController.navigate(Screen.Password.route) {
                launchSingleTop = true
            }
        } else {
            if (navController.previousBackStackEntry == null) {
                navController.navigate(Screen.Home.route) {
                    popUpTo(Screen.Password.route) {
                        inclusive = true
                    }
                }
            } else {
                navController.popBackStack()
            }
        }
    }