Introduction
Hello guys 👋👋, welcome back to another article, in our previous article
we
discussed how to inspect network traffic using the Chucker dev extension in android.
In this article, I will show you a trick that can save you time when dealing with the nuisances of Navigation Compose
If you've used navigation compose, you may have noticed how sometimes it can
be a headache because it lacks compile time type safety, hence sometimes when
you navigate to a given route, your app crashes.This problem has led to the creation of
type safe navigation libraries like compose destinations, voyager etc.
This can reduce your productivity as may spend time to debug the crash.
Basically, to prevent the reoccurrence such crashes, we should abstract our
navigation definitions through state hoisting. Don't understand what this
means ....read on
Basically, state hoisting is practise in Jetpack Compose where we only expose
state and functions that modify the state to the composable.This results to
having 2 versions of one composable, Stateless and a stateful one.For more
information and the benefits of this practise,
read this article
by me
How we navigate In Jetpack Compose
Normally we navigate in compose by passing the navigation logic to the
onClick lambda where its needed as shown below
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
navController.navigate(route="login")
}
) {
Text(text = "Login")
}
The problem with this approach is that when if the NavHost where this navController
is defined does not have a route called "login", the app will crash. Normally if
you have one NavHost this won't be the issue since there is only one instance
of the navController(Unless you create a new one in your composable), but when
your app has a bottom Nav bar that requires its own NavHost, this approach can
become an issue since now you have multiple navControllers
Solution
To solve this issue, we can define all necessary navigation definitions in
our NavHost via explicit lambdas or extension functions to the NavController
class. This way we know what NavController has a route definition as shown below
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screens.DASHBOARD_SCREEN
) {
composable(route = Screens.LOGIN_SCREEN) {
LoginScreen(
navigateToDashBoard = navController::navigateToDashBoard,
navigateToSignUpScreen = navController::navigateToSignUpScreen,
)
}
composable(route = Screens.SIGNUP_SCREEN) {
SignUpScreen(
navigateToLoginScreen = navController::navigateToLoginScreen,
)
}
composable(route = Screens.DASHBOARD_SCREEN) {
DashboardScreen(
navigateToLoginScreen = navController::navigateToLoginScreen,
)
}
}
This way we can pass the navigation functions to the composables without explictly
having to define the navigation logic each time we need it. If we get the navigation
logic right top level, we won't need to worry about getting it right when actually
navigating to the various screens.
Once again this won't help much if you have 1 NavHost you will see its benefits if
you have a bottom App Bar in your application
I hope this tricks helps you build better apps using Jetpack compose.
Don't forget to clap for this article and leave a comment for any questions
While you are at it, you can follow my GitHub
profile to see some projects this in concept in practice
Top comments (2)
Heyy Peter Chege, you can Improve your post by adding pictures,GIF's and emoji's.😁
nice Post ❤️
Thank you
Next time I will add them :)