Navigation.

Apps have multiple screens. Users move between them. Navigate forward to see details. Navigate back to return. Today we understand how to handle navigation in Android, both in traditional Views and in Compose.

Navigation is moving between destinations.

A destination is a screen or content the user can reach. A home screen. A detail screen. A settings screen.

Navigation forms a graph. Destinations are nodes. Transitions are edges. Users traverse this graph.

The back stack tracks navigation history. Each navigation adds to the stack. Back removes from it.

Press back, the current destination pops. The previous one shows. Empty stack, the app exits.

Android provides a Navigation component.

It handles navigation, back stack, arguments, animations. A unified API across fragments and Compose.

You define a navigation graph. Destinations and actions between them. The component manages the rest.

NavController is the core object. It performs navigation. It tracks the back stack.

NavHost displays the current destination. It swaps content as you navigate.

In Compose, use NavHost to set up navigation.

NavHost navController equals navController startDestination equals "home" brace composable "home" HomeScreen composable "details" DetailsScreen close brace.

Each composable call registers a destination. The route string identifies it.

Navigate with navController dot navigate "details". The NavHost shows DetailsScreen.

Pop back with navController dot popBackStack. Or just press the back button.

Create NavController with rememberNavController.

val navController equals rememberNavController. This creates and remembers the controller.

Pass it to NavHost. NavHost navController equals navController.

Pass it to screens that need to navigate. Or better, pass only lambda callbacks.

Do not pass NavController deep into the hierarchy. Pass navigation actions as lambdas instead.

Screens often need data. Show details for item 42. Load user with ID abc.

Define arguments in the route. composable "details slash itemId" type equals NavType dot IntType. The route includes a placeholder.

Navigate with the argument. navController dot navigate "details slash 42".

Access in the destination. backStackEntry dot arguments question dot getInt "itemId".

Arguments pass data between destinations. Required or optional. Typed.

A user list navigating to user details.

NavHost brace composable "users" UserListScreen onUserClick equals brace userId arrow navController dot navigate "user slash userId" close brace composable "user slash userId" entry arrow val id equals entry dot arguments... UserDetailScreen id close brace close brace.

User clicks an item. Navigation happens with the user ID. Detail screen extracts and uses it.

This is a common pattern. List to detail navigation with passed identifier.

The back stack is a stack of destinations.

navigate adds to the stack. popBackStack removes.

Sometimes you want special behavior. Navigate but clear history. Navigate and replace current.

navigate "home" brace popUpTo "home" inclusive equals true close brace. This clears back to home, then navigates to home. Useful for login completion.

launchSingleTop equals true prevents duplicate destinations. Navigate to A when already on A does nothing.

Keep navigation logic at a high level.

Screens should not know about routes. They receive callbacks.

UserListScreen onUserClick colon Int arrow Unit. The screen calls onUserClick with the ID.

The host composes with navigation. onUserClick equals brace navController dot navigate "user slash it" close brace.

This separates screens from navigation. Screens are reusable. Navigation is centralized.

Let us summarize.

Navigation moves between destinations through a navigation graph.

NavController handles navigation and back stack management.

NavHost in Compose displays the current destination.

Pass arguments through routes for data like IDs.

Manage back stack with popUpTo and launchSingleTop.

Keep screens decoupled from navigation by using callbacks.