Как реализовать навигацию в Jetpack Compose?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Навигация в Jetpack Compose
Навигация в Jetpack Compose реализуется через Navigation Compose библиотеку, которая предоставляет компонентный подход к управлению маршрутами и стеком экранов.
1. Базовая установка
Прежде всего нужно добавить зависимость в build.gradle:
implementation "androidx.navigation:navigation-compose:2.7.x"
2. NavController и NavHost
Основные компоненты навигации:
@Composable
fun App() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") { HomeScreen(navController) }
composable("details/{id}") { backStackEntry ->
val id = backStackEntry.arguments?.getString("id")
DetailsScreen(id = id, navController = navController)
}
}
}
NavController управляет навигацией и содержит информацию о текущем маршруте. NavHost это контейнер, отображающий компонент в зависимости от текущего маршрута.
3. Типизированная навигация с Route
Вместо строк лучше использовать sealed class или data class для типобезопасности:
sealed class Route {
data object Home : Route()
data class Details(val id: String) : Route()
data object Settings : Route()
}
@Composable
fun App() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Route.Home
) {
composable<Route.Home> {
HomeScreen(
onNavigate = { route -> navController.navigate(route) }
)
}
composable<Route.Details> { backStackEntry ->
val args = backStackEntry.toRoute<Route.Details>()
DetailsScreen(id = args.id)
}
}
}
4. Навигация между экранами
Основные операции навигации:
// Переход на новый экран
navController.navigate(Route.Details(id = "123"))
// С сохранением в backstack
navController.navigate(Route.Home) {
popUpTo(Route.Details) { inclusive = true }
}
// Возврат назад
navController.popBackStack()
// Очистить весь backstack
navController.popBackStack(Route.Home, inclusive = false)
5. Передача аргументов
Передача данных между экранами:
@Composable
fun HomeScreen(onNavigate: (Route) -> Unit) {
Button(
onClick = {
onNavigate(Route.Details(id = "user123"))
}
) {
Text("Go to Details")
}
}
@Composable
fun DetailsScreen(id: String) {
Text("Showing details for: $id")
}
6. Deep Links
Поддержка deep links для открытия приложения с определённого экрана:
navigraphmodule/
composable<Route.Details>(
deepLinks = listOf(
navDeepLink<Route.Details>("https://example.com/details/{id}")
)
) { backStackEntry ->
val args = backStackEntry.toRoute<Route.Details>()
DetailsScreen(id = args.id)
}
7. Сохранение состояния при навигации
По умолчанию Compose пересоздаёт компоненты при навигации. Для сохранения состояния:
NavHost(
navController = navController,
startDestination = Route.Home
) {
composable<Route.Home>(
enterTransition = { fadeIn() },
exitTransition = { fadeOut() }
) {
HomeScreen()
}
}
8. Вложенная навигация (Nested Navigation)
Для сложных приложений с несколькими потоками (home, search, profile):
NavHost(navController, startDestination = "home") {
navigation<Route.Home>(startDestination = Route.HomeMain) {
composable<Route.HomeMain> { HomeScreen() }
composable<Route.HomeDetails> { DetailsScreen() }
}
navigation<Route.Profile>(startDestination = Route.ProfileMain) {
composable<Route.ProfileMain> { ProfileScreen() }
}
}
9. ViewModel и Hilt с навигацией
Использование ViewModel, который сохраняет состояние при пересоздании композитов:
@HiltViewModel
class DetailsViewModel @Inject constructor(
val repository: Repository
) : ViewModel() {
val uiState = mutableStateOf<UiState>(UiState.Loading)
}
@Composable
fun DetailsScreen(
viewModel: DetailsViewModel = hiltViewModel()
) {
// viewModel сохранится при навигации
}
Best Practices
- Используйте типизированные маршруты вместо строк
- Держите ViewModel в памяти при поп-бэке
- Избегайте перемещения слишком большого количества данных между маршрутами
- Используйте SavedStateHandle для сохранения состояния
- Правильно обрабатывайте backstack при нескольких потоках навигации