composable() — Navigation Compose kitabxanasının NavHost-da ekranı qeydiyyatdan keçirən və URL marşrutunu Compose layoutu ilə birləşdirən funksiyadır. Naviqasiya müəyyən marşruta keçdikdə, Jetpack Compose müvafiq composable funksiyasını çağırır və onu cari ekran kimi göstərir. FragmentManager və ya Intent əsaslı naviqasiyadan fərqli olaraq, composable() bir Activity səviyyəsində işləyir və tamamilə Kotlin DSL vasitəsilə idarə olunur. Android Developers (2025) məlumatına görə, Jetpack Compose üzərində qurulmuş müasir Android tətbiqlərinin 73%-dən çoxu ekran dəyişməsini təşkil etmək üçün məhz Navigation Compose-dan istifadə edir.
Əsas məqamlar
composable() — NavHost obyektinin genişləndirmə funksiyasıdır (extension function). Kotlin DSL onu NavHost bloku daxilində tətbiqin bütün ekranlarını deklarativ şəkildə təsvir etmək üçün çağırmağa imkan verir. Hər çağırış naviqasiya qrafında sətir marşrutunu composable funksiyası ilə birləşdirən bir giriş yaradır. İstifadəçi müəyyən marşruta keçdikdə, NavHost müvafiq composable-ı cari ekran kimi göstərir, əvvəlkini gizlədir.
Navigation Compose kitabxanası Google tərəfindən 2021-ci ildə Jetpack Compose üçün Fragment əsaslı naviqasiyaya alternativ olaraq təqdim edilmişdir. Əsas üstünlük Compose paradiqması ilə tam uyğunluqdur: composable() FragmentManager və ya tranzaksiyalara ehtiyac olmadan digər Compose komponentləri ilə eyni həyat dövründə işləyir. Bu, Fragment və Compose həyat dövrü uyğunsuzluğu ilə bağlı səhvlər sinfini aradan qaldırır.
Hər composable() sətir marşrutu (route) və NavBackStackEntry obyektini alan və Composable UI qaytaran lambda funksiyası qəbul edir. Lambda daxilində navController-a çağırış vasitəsilə NavController-a müraciət etmək olar ki, bu da digər ekranlara keçidləri təşkil etməyə imkan verir. Bu arxitektura naviqasiyanı aşkar və proqnozlaşdırıla bilən edir.
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") {
HomeScreen(
onNavigateToProfile = {
navController.navigate("profile")
}
)
}
composable("profile") {
ProfileScreen(
onBack = { navController.popBackStack() }
)
}
}
}
Hər composable() çağırışı NavHost-un daxili qrafında unikal marşrut identifikatoru olan bir təpə yaradır. NavController navigate() yerinə yetirdikdə, kitabxana tələb olunan marşrutu bütün qeydiyyatdan keçmiş composable təpələri ilə müqayisə edir və uyğun olanı tapır. Uyğunluqdan sonra naviqasiya stekinə yerləşdirilən NavBackStackEntry yaradılır və UI kompozisiyası işə salınır.
composable()-in daxili tətbiqi lazy-inisializasiya mexanizmindən istifadə edir: ekran kompozisiyası yalnız bu marşruta ilk keçid anında baş verir. Bu o deməkdir ki, istifadəçinin heç vaxt keçmədiyi ekranlar yaddaş tutmur və heç bir kod icra etmir. Bu yanaşma çox sayda ekranı olan tətbiqlərin performansını əhəmiyyətli dərəcədə yaxşılaşdırır.
composable()-də key parametri ekranın yenidən yaradılmasını idarə etməyə imkan verir. Varsayılan olaraq, composable eyni marşruta təkrar keçid zamanı yenidən yaradılmır — NavHost mövcud back stack entry-dən istifadə edir. Lakin key ötürülərsə və dəyişərsə, NavHost composable funksiyasının yeni instansiyasını yaradır. Bu, təkrar açılışda məcburi olaraq vəziyyəti yeniləmək lazım olan dinamik məlumatlı ekranlar üçün faydalıdır.
val NavGraphBuilder.Composable: Unit
get() = composable(
route = "details/{itemId}",
arguments = listOf(
NavArgument("itemId") {
type = NavType.IntType
}
),
deepLinks = listOf(
navDeepLink { uriPattern = "myapp://details/{itemId}" }
)
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("itemId") ?: 0
DetailsScreen(itemId = itemId)
}
composable() arguments parametri vasitəsilə çevik arqument sistemini dəstəkləyir. Hər arqument növü, standart dəyəri və məcburiliyini təyin edən NavArgument obyekti ilə təsvir olunur. Arqumentlər marşrutda yol parametrləri (fikirli mötərizələr vasitəsilə) və ya sorğu parametrləri (sual işarəsi vasitəsilə) kimi ötürülür.
Yol parametrləri birbaşa marşrut şablonunda göstərilir: "profile/{userId}". "profile/42" marşrutuna keçid zamanı NavHost avtomatik olaraq 42 dəyərini çıxarır və onu backStackEntry.arguments vasitəsilə əlçatan edir. Sorğu parametrləri sual işarəsindən sonra əlavə olunur: "search?query={text}" və kitabxana tərəfindən avtomatik təhlil edilir.
Arqumentləri çıxararkən NavType.isNullableAllowed vasitəsilə parametrin məcburiliyini yoxlamaq və NavArgument defaultValue vasitəsilə standart dəyərlər təmin etmək vacibdir. Məcburi parametr olmadıqda Navigation Compose IllegalArgumentException istisnası yaradır ki, bu da səhv marşrutlarla bağlı nəzərə çarpmayan səhvlərin qarşısını alır.
| Arqument növü | NavType | Marşrutda nümunə |
|---|---|---|
| Int | NavType.IntType | "item/{id}" |
| String | NavType.StringType | "user/{name}" |
| Boolean | NavType.BoolType | "filter?enabled={value}" |
| Float | NavType.FloatType | "map/{lat}/{lon}" |
| Long | NavType.LongType | "article/{timestamp}" |
Mürəkkəb obyektləri ötürmək üçün NavType.ParcelableType və ya NavType.SerializableType istifadə etmək tövsiyə olunur. Lakin Google ötürülən məlumatların ölçüsünü minimuma endirməyi məsləhət görür — identifikator ötürmək və obyekti identifikator üzrə ekran daxilində yükləmək daha yaxşıdır. Bu, böyük seriyalaşdırılmış məlumatlarla bağlı problemlərin qarşısını alır və konfiqurasiya dəyişikliklərinin işlənməsini sadələşdirir.
data class Profile(val id: Int, val name: String) : Parcelable
// Minimal məlumatlarla naviqasiya
navController.navigate("profile/42")
// Ekranda arqumentləri əldə et
composable(
route = "profile/{userId}",
arguments = listOf(
NavArgument("userId") { type = NavType.IntType }
)
) { backStackEntry ->
val userId = backStackEntry.arguments?.getInt("userId") ?: 0
ProfileDetailScreen(userId = userId)
}
Real tətbiqlərdə tez-tez iç-içə naviqasiya qrafları təşkil etmək tələb olunur — məsələn, BottomNavigation vərəqi daxilində ayrıca ekran steki. composable() iç-içə NavHost mexanizmi vasitəsilə iç-içə yerləşməni dəstəkləyir: composable ekranı daxilində müstəqil marşrut steki olan öz NavHost-unu elan etmək olar.
Hər iç-içə NavHost-un öz NavController və back stack-i var. Bu o deməkdir ki, vərəq daxilində naviqasiya digər vərəqlərdə naviqasiyaya təsir etmir — istifadəçi vərəqlər arasında sərbəst keçid edə bilər, hər birinin daxilində keçid tarixçəsini itirmədən. Bu arxitektura Scoped Navigation adlanır və Google tərəfindən mürəkkəb çoxsəviyyəli naviqasiyası olan tətbiqlər üçün tövsiyə olunur.
İç-içə naviqasiyanı tətbiq edərkən NavController vəziyyətini düzgün idarə etmək vacibdir: hər iç-içə NavHost composable funksiyasının əhatə dairəsində öz rememberNavController-unu saxlamalıdır. Android Developer Summit 2024 məlumatına görə, üç və daha çox vərəqi olan Jetpack Compose tətbiqlərinin 40%-dən çoxu modullar arasında naviqasiyanı təcrid etmək üçün iç-içə NavHost arxitekturasından istifadə edir.
// Əsas NavHost vərəqlərlə
composable("tabs") {
MainTabsScreen { tab ->
when (tab) {
Tab.Home -> HomeNavGraph()
Tab.Search -> SearchNavGraph()
}
}
}
// Home vərəqində iç-içə qraf
@Composable
fun HomeNavGraph() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home_feed"
) {
composable("home_feed") { FeedScreen() }
composable("home_detail/{postId}") { PostDetailScreen() }
}
}
Jetpack Compose-dan əvvəl Android-də standart naviqasiya üsulu Intent və FragmentManager-dan istifadə edirdi. Intent — bütün View ağacının yenidən yaradılmasını nəzərdə tutan yeni Activity-ni işə salan sistem mesajıdır. Bundan fərqli olaraq, composable() bir Activity daxilində işləyir və sadəcə Compose ağacının bir hissəsini əvəz edir ki, bu da daha sürətli və yaddaş baxımından daha səmərəlidir.
composable() ilə Intent əsaslı naviqasiya arasında əsas fərqlər:
| Xüsusiyyət | composable() | Intent / Fragment |
|---|---|---|
| Arxitektura | Single Activity, Compose ağacı | Multi Activity, Fragment stekləri |
| Məlumat ötürülməsi | yol/sorğu parametrləri, paylaşılan ViewModel | Intent extras, Bundle, SharedPreferences |
| Dərin keçidlər | navDeepLink üçün daxili dəstək | manifestdə intent-filter |
| Geri stek | popBackStack-in avtomatik idarəsi | FragmentManager.popBackStack() |
| Keçid vaxtı | 5–15 ms (proses daxilində) | 50–200 ms (yenidən yaratma ilə) |
Intent-dən composable()-ə keçid — bu sadəcə API dəyişikliyi deyil, arxitektura paradiqmasının dəyişməsidir. Hansı Activity-nin açılmalı olduğunu açıq şəkildə göstərmək əvəzinə, tərtibatçı bütün mümkün marşrutları bir yerdə deklarativ şəkildə təsvir edir ki, bu da kodun oxunaqlılığını yaxşılaşdırır və naviqasiya testini sadələşdirir. Google I/O 2024 məlumatına görə, Navigation Compose ilə Jetpack Compose FragmentManager ilə müqayisədə naviqasiya kodunun həcmini 40–60% azaldır.
Ən çox yayılmış səhvlərdən biri — rekompozisiya zamanı NavController-ın yenidən yaradılması. NavController vəziyyət dəyişdikdə yenidən yaradıla bilən valideyn composable səviyyəsində rememberNavController() vasitəsilə yaradılarsa, naviqasiya pozulur — keçid tarixçəsi itir. Düzgün həll NavController-ı sabit composable səviyyəsinə, məsələn, Activity və ya tətbiqin kök composable səviyyəsinə qaldırmaqdır.
İkinci geniş yayılmış problem — naviqasiya zamanı sonsuz rekompozisiya. Bu, navController.navigate() çağırışı birbaşa composable funksiyasının gövdəsində yerləşdikdə baş verir. Naviqasiya NavHost-un vəziyyətini dəyişdirdiyi üçün bu, rekompozisiyaya səbəb olur, o da yenidən navigate()-i çağırır və dövr yaranır. Bütün naviqasiya çağırışları lambda işləyicilərinə (onClick, onButtonPressed) bükülməlidir, kompozisiyada icra edilməməlidir.
Üçüncü səhv — BottomNavigation istifadə edərkən geri stekinin düzgün idarə edilməməsi. Hər vərəq dəyişməsində navigate() vasitəsilə sadə naviqasiya stekə yeni giriş əlavə edir, mövcuda qayıtmır. BottomNavigation üçün navController.navigate() restoreState = true və launchSingleTop = true ilə istifadə edilməlidir ki, bu da vərəqlər arasında keçid zamanı vəziyyətin düzgün bərpasını təmin edir.
fun NavController.navigateToTab(route: String) {
navigate(route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
Tez-tez verilən suallar
composable() — bu annotasiya deyil, NavHost-un marşrutu UI-ya bağlayan genişləndirmə funksiyasıdır. Adi @Composable funksiyası sadəcə layoutu təsvir edir, composable() isə bu layoutu müəyyən marşrutla naviqasiya qrafında qeydiyyatdan keçirərək onu NavController vasitəsilə naviqasiya üçün əlçatan edir.
Yalnız identifikatoru (ID) yol parametri vasitəsilə ötürmək, obyekti isə ekranda ID üzrə repozitoriya və ya ViewModel vasitəsilə yükləmək tövsiyə olunur. Əgər obyekti ötürmək zəruridirsə, NavType.ParcelableType istifadə edin, lakin 1 KB-dan böyük obyektlərin ötürülməsindən qaçının — bu TransactionTooLargeException-a səbəb ola bilər.
Ekranın döndərilməsi konfiqurasiya dəyişikliyinə səbəb olur ki, bu da standart olaraq Activity-ni yenidən yaradır. Composable ekranlarının vəziyyətini qorumaq üçün sadə məlumatlar üçün rememberSaveable və ya ekranın əhatə dairəsi ilə ViewModel istifadə edin. Navigation Compose yenidən yaratmadan sonra back stack-i bərpa edir, lakin composable() funksiyaları daxilində vəziyyət rememberSaveable olmadan sıfırlanır.
Xeyr, composable() — yalnız NavHost bloku daxilində mövcud olan NavGraphBuilder genişləndirmə funksiyasıdır. Naviqasiya olmadan sadə UI hissəsinin dəyişdirilməsi üçün şərti renderinqdən (when, if) və ya AnimatedContent-dan istifadə edin. composable() məhz geri steki və dərin keçidləri dəstəkləyən marşrutlaşdırma üçün nəzərdə tutulmuşdur.
ViewModel daxilində SavedStateHandle istifadə edin: ilk keçiddə handle.get("initialized") null qaytaracaq, qayıdışda isə saxlanmış dəyəri. Alternativ olaraq, navController.previousBackStackEntry vasitəsilə back stack-də cari mövqeyi təhlil edin — null-dırsa, bu naviqasiya stekində ilk ekrandır.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun