The app is built with a single activity. The host activity is simple. The content is set to the NavHostController that starts out with the Home screen

Here's what the app activity looks like


@AndroidEntryPoint
class ScaffoldActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NationalParksApp()
        }
    }
}

Creating a navigation controller

The navigation controller is one of the key concepts in navigation. It holds the navigation graph and exposes methods that allow your app to move between the destinations in the graph.

When using the Navigation component, you create a navigation controller using the NavController class. NavController is the central navigation API. It tracks which destinations the user has visited, and allows the user to move between destinations. This guide demonstrates how to create a NavController in your app.

This is an example of the Navigation Controller in our National Park app


@Composable
fun NationalParksApp() {
    val navController = rememberNavController()
    NationalParksNavHost(
        navController = navController
    )
}

@Composable
fun NationalParksNavHost(
    navController: NavHostController
) {
    val activity = (LocalContext.current as Activity)
    NavHost(navController = navController, startDestination = Screen.Home.route) {
        composable(route = Screen.Home.route) {
            HomeScreen(
                onParkClick = {
                    navController.navigate(
                        Screen.Park.createRoute(
                            parkId = it.parkCode,
                            parkTitle = it.fullName,
                        )
                    )
                }
            )
        }

        composable(
            route = Screen.Park.route,
            arguments = Screen.Park.navArguments
        ) {
            ParkScreen(
                onBackClick = { navController.navigateUp() },
                onFabClick = {
                    navController.navigateUp()
                }, onGoToGalleryClick = {
                    navController.navigate(
                        Screen.Gallery.createRoute(it)
                    )
                }
            )
        }
    

val navController = rememberNavController()

This line creates a nav controller. It's important to note that this line needs to be high in the composable hierarchy. It needs to be high enough so that all the composables that need to reference it can do so.

The NavController will act as a single source of truth for updating composables outside of your screens. This follows the principles of State hoisting in Jetpack Compose

Create a NavHost


@Composable
fun NationalParksNavHost(
    navController: NavHostController
) {
    val activity = (LocalContext.current as Activity)
    NavHost(navController = navController, startDestination = Screen.Home.route) {
        composable(route = Screen.Home.route) {
            HomeScreen(
                onParkClick = {
                    navController.navigate(
                        Screen.Park.createRoute(
                            parkId = it.parkCode,
                            parkTitle = it.fullName,
                        )
                    )
                }
            )
        }

		
  1. The call to the NavHost composable passes a NavController and a route string that corresponds to the start destination.
  2. The lambda passed to the NavHost ultimately calls NavController.creatGraph() and returns a NavGraph.
  3. The calls to NavGraphBuilder.composable() add destinations to the resulting NavGraph.
  4. In this case, the destinations are the Profile and FriendsList composables. The route strings "profile" and "friendslist" become the keys that identify the two destinations.

Links:

https://developer.android.com/guide/navigation/navcontroller
https://developer.android.com/guide/navigation/design#compose