composable() — bu Navigation Compose kutubxonasining NavHost-da ekranni ro'yxatdan o'tkazadigan va URL marshrutini Compose layouti bilan bog'laydigan funksiyasi. Navigatsiya belgilangan marshrutga o'tganda, Jetpack Compose tegishli composable funksiyasini chaqiradi va uni joriy ekran sifatida ko'rsatadi. FragmentManager yoki Intent asosidagi navigatsiyadan farqli o'laroq, composable() bitta Activity darajasida ishlaydi va to'liq Kotlin DSL orqali boshqariladi. Android Developers (2025) ma'lumotlariga ko'ra, Jetpack Compose asosida qurilgan zamonaviy Android ilovalarining 73% dan ortig'i ekranlarni o'zgartirishni tashkil qilish uchun aynan Navigation Compose-dan foydalanadi.
Asosiy fikrlar
composable() — bu NavHost ob'ektining kengaytma funksiyasi (extension function). Kotlin DSL uni NavHost bloki ichida ilovaning barcha ekranlarini deklarativ tarzda tavsiflash uchun chaqirishga imkon beradi. Har bir chaqiruv navigatsiya grafigida matn marshrutini composable funksiyasi bilan bog'laydigan yozuv yaratadi. Foydalanuvchi ma'lum bir marshrutga o'tganda, NavHost tegishli composable-ni joriy ekran sifatida ko'rsatadi, oldingisini yashiradi.
Navigation Compose kutubxonasi Google tomonidan 2021-yilda Jetpack Compose uchun Fragment asosidagi navigatsiyaga alternativa sifatida taqdim etilgan. Asosiy afzallik — Compose paradigmasiga to'liq moslik: composable() FragmentManager yoki tranzaksiyalarga ehtiyoj sezmasdan boshqa Compose komponentlari bilan bir xil hayot tsiklida ishlaydi. Bu Fragment va Compose hayot tsiklining mos kelmasligi bilan bog'liq xatolar sinfini yo'q qiladi.
Har bir composable() matn marshruti (route) va NavBackStackEntry ob'ektini oladigan va Composable UI qaytaradigan lambda funksiyasini qabul qiladi. Lambda ichida navController chaqiruvi orqali NavController-ga murojaat qilish mumkin, bu esa boshqa ekranlarga o'tishlarni tashkil qilish imkonini beradi. Bunday arxitektura navigatsiyani aniq va bashorat qilinadigan qiladi.
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") {
HomeScreen(
onNavigateToProfile = {
navController.navigate("profile")
}
)
}
composable("profile") {
ProfileScreen(
onBack = { navController.popBackStack() }
)
}
}
}
Har bir composable() chaqiruvi NavHost-ning ichki grafigida noyob marshrut identifikatoriga ega tugun yaratadi. NavController navigate() ni bajarganida, kutubxona so'ralgan marshrutni barcha ro'yxatdan o'tgan composable tugunlari bilan solishtiradi va mos keladiganini topadi. Moslikdan so'ng navigatsiya stekiga joylashtiriladigan NavBackStackEntry yaratiladi va UI kompozitsiyasi boshlanadi.
composable()-ning ichki amalga oshirilishi lazy-initsializatsiya mexanizmidan foydalanadi: ekran kompozitsiyasi faqat ushbu marshrutga birinchi o'tish paytida sodir bo'ladi. Bu foydalanuvchi hech qachon o'tmagan ekranlar xotirani egallamasligi va hech qanday kod bajarmasligini anglatadi. Bunday yondashuv ko'p sonli ekranlarga ega ilovalarning unumdorligini sezilarli darajada yaxshilaydi.
composable()-dagi key parametri ekranni qayta yaratishni boshqarish imkonini beradi. Odatiy bo'lib, composable bir xil marshrutga takroriy o'tishda qayta yaratilmaydi — NavHost mavjud back stack yozuvidan foydalanadi. Agar key uzatilsa va o'zgarsa, NavHost composable funksiyasining yangi instansiyasini yaratadi. Bu qayta ochishda holatni majburiy ravishda yangilash kerak bo'lgan dinamik ma'lumotli ekranlar uchun foydalidir.
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 orqali moslashuvchan argument tizimini qo'llab-quvvatlaydi. Har bir argument turi, standart qiymati va majburiyligini belgilaydigan NavArgument ob'ekti bilan tavsiflanadi. Argumentlar marshrutda yo'l parametrlari (jingalak qavslar orqali) yoki so'rov parametrlari (savol belgisi orqali) sifatida uzatiladi.
Yo'l parametrlari to'g'ridan-to'g'ri marshrut shablonida ko'rsatiladi: "profile/{userId}". "profile/42" marshrutiga o'tishda NavHost avtomatik ravishda 42 qiymatini chiqaradi va uni backStackEntry.arguments orqali mavjud qiladi. So'rov parametrlari savol belgisidan keyin qo'shiladi: "search?query={text}" va ham kutubxona tomonidan avtomatik tahlil qilinadi.
Argumentlarni chiqarishda NavType.isNullableAllowed orqali parametrning majburiyligini tekshirish va NavArgument defaultValue orqali standart qiymatlarni taqdim etish muhimdir. Majburiy parametr mavjud bo'lmaganda, Navigation Compose IllegalArgumentException istisnosini yaratadi, bu noto'g'ri marshrutlar bilan bog'liq sezilmas xatolarning oldini oladi.
| Argument turi | NavType | Marshrutda misol |
|---|---|---|
| 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}" |
Murakkab ob'ektlarni uzatish uchun NavType.ParcelableType yoki NavType.SerializableType dan foydalanish tavsiya etiladi. Google uzatiladigan ma'lumotlar hajmini minimallashtirishni maslahat beradi — identifikatorni uzatish va ob'ektni identifikator bo'yicha ekran ichida yuklash yaxshiroqdir. Bu katta seriyalashtirilgan ma'lumotlar bilan bog'liq muammolarning oldini oladi va konfiguratsiya o'zgarishlarini qayta ishlashni soddalashtiradi.
data class Profile(val id: Int, val name: String) : Parcelable
// Minimal ma'lumotlar bilan navigatsiya
navController.navigate("profile/42")
// Ekranda argumentlarni olish
composable(
route = "profile/{userId}",
arguments = listOf(
NavArgument("userId") { type = NavType.IntType }
)
) { backStackEntry ->
val userId = backStackEntry.arguments?.getInt("userId") ?: 0
ProfileDetailScreen(userId = userId)
}
Haqiqiy ilovalarda ko'pincha ichma-ich navigatsiya graflarini tashkil qilish talab etiladi — masalan, BottomNavigation varag'i ichida alohida ekranlar steki. composable() ichma-ich NavHost mexanizmi orqali ichma-ichlikni qo'llab-quvvatlaydi: composable ekrani ichida mustaqil marshrut stekiga ega o'z NavHost-ni e'lon qilish mumkin.
Har bir ichma-ich NavHost o'z NavController va back stack-iga ega. Bu varaq ichidagi navigatsiya boshqa varaqlardagi navigatsiyaga ta'sir qilmasligini anglatadi — foydalanuvchi varaqlar o'rtasida erkin almashishi mumkin, har birining ichidagi o'tish tarixini yo'qotmasdan. Bunday arxitektura Scoped Navigation deb ataladi va Google tomonidan murakkab ko'p darajali navigatsiyaga ega ilovalar uchun tavsiya etiladi.
Ichma-ich navigatsiyani amalga oshirishda NavController holatini to'g'ri boshqarish muhim: har bir ichma-ich NavHost composable funksiyasi doirasida o'z rememberNavController-ni saqlashi kerak. Android Developer Summit 2024 ma'lumotlariga ko'ra, uch va undan ortiq varag'i bo'lgan Jetpack Compose ilovalarining 40% dan ortig'i modullar o'rtasida navigatsiyani izolyatsiya qilish uchun ichma-ich NavHost arxitekturasidan foydalanadi.
// Asosiy NavHost varaqlar bilan
composable("tabs") {
MainTabsScreen { tab ->
when (tab) {
Tab.Home -> HomeNavGraph()
Tab.Search -> SearchNavGraph()
}
}
}
// Home varag'idagi ichma-ich graf
@Composable
fun HomeNavGraph() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home_feed"
) {
composable("home_feed") { FeedScreen() }
composable("home_detail/{postId}") { PostDetailScreen() }
}
}
Jetpack Compose-dan oldin Android-da standart navigatsiya usuli Intent va FragmentManager-dan foydalanardi. Intent — butun View daraxtining qayta yaratilishini nazarda tutadigan yangi Activity-ni ishga tushiradigan tizim xabaridir. Bundan farqli o'laroq, composable() bitta Activity ichida ishlaydi va shunchaki Compose daraxtining bir qismini almashtiradi, bu esa sezilarli darajada tezroq va xotira jihatidan samaraliroqdir.
composable() va Intent asosidagi navigatsiya o'rtasidagi asosiy farqlar:
| Xususiyat | composable() | Intent / Fragment |
|---|---|---|
| Arxitektura | Single Activity, Compose daraxti | Multi Activity, Fragment steklari |
| Ma'lumot uzatish | yo'l/so'rov parametrlari, umumiy ViewModel | Intent extras, Bundle, SharedPreferences |
| Chuqur havolalar | navDeepLink uchun o'rnatilgan qo'llab-quvvatlash | manifestda intent-filter |
| Orqaga stek | popBackStack-ni avtomatik boshqarish | FragmentManager.popBackStack() |
| Almashtirish vaqti | 5–15 ms (jarayon ichida) | 50–200 ms (qayta yaratish bilan) |
Intent-dan composable()-ga o'tish — bu shunchaki API o'zgarishi emas, balki arxitektura paradigmasining o'zgarishidir. Qaysi Activity ochilishi kerakligini aniq ko'rsatish o'rniga, dasturchi barcha mumkin bo'lgan marshrutlarni bir joyda deklarativ tarzda tavsiflaydi, bu kodning o'qilishini yaxshilaydi va navigatsiyani test qilishni soddalashtiradi. Google I/O 2024 ma'lumotlariga ko'ra, Navigation Compose bilan Jetpack Compose FragmentManager bilan solishtirganda navigatsiya kodi hajmini 40–60% ga kamaytiradi.
Eng keng tarqalgan xatolardan biri — rekompozitsiya paytida NavController-ni qayta yaratish. Agar NavController holat o'zgarganda qayta yaratilishi mumkin bo'lgan ota-composable darajasida rememberNavController() orqali yaratilsa, navigatsiya buziladi — o'tish tarixi yo'qoladi. To'g'ri yechim NavController-ni barqaror composable darajasiga, masalan, Activity yoki ilovaning ildiz composable darajasiga ko'tarishdir.
Ikkinchi keng tarqalgan muammo — navigatsiya paytida cheksiz rekompozitsiya. Bu navController.navigate() chaqiruvi to'g'ridan-to'g'ri composable funksiyasining tanasida joylashtirilganda sodir bo'ladi. Navigatsiya NavHost holatini o'zgartirgani sababli, bu rekompozitsiyani keltirib chiqaradi, u yana navigate()-ni chaqiradi va sikl hosil qiladi. Barcha navigatsiya chaqiruvlari lambda ishlovchilariga (onClick, onButtonPressed) o'ralishi kerak, kompozitsiyada bajarilmasligi kerak.
Uchinchi xato — BottomNavigation dan foydalanishda orqaga stekini noto'g'ri boshqarish. Har bir varaqni almashtirishda navigate() orqali oddiy navigatsiya stekka yangi yozuv qo'shadi, mavjudga qaytmaydi. BottomNavigation uchun navController.navigate() restoreState = true va launchSingleTop = true bilan ishlatilishi kerak, bu varaqlar o'rtasida almashishda holatni to'g'ri tiklashni ta'minlaydi.
fun NavController.navigateToTab(route: String) {
navigate(route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
Tez-tez beriladigan savollar
composable() — bu annotatsiya emas, balki NavHost-ning marshrutni UI bilan bog'laydigan kengaytma funksiyasidir. Oddiy @Composable funksiyasi shunchaki layoutni tavsiflaydi, composable() esa bu layoutni belgilangan marshrut bilan navigatsiya grafigida ro'yxatdan o'tkazadi va uni NavController orqali navigatsiya uchun mavjud qiladi.
Faqat identifikatorni (ID) yo'l parametri orqali uzatish, ob'ektni esa ID bo'yicha ekranda repository yoki ViewModel orqali yuklash tavsiya etiladi. Agar ob'ektni uzatish zarur bo'lsa, NavType.ParcelableType dan foydalaning, lekin 1 KB dan katta ob'ektlarni uzatishdan saqlaning — bu TransactionTooLargeException ga olib kelishi mumkin.
Ekran aylantirilishi konfiguratsiya o'zgarishiga sabab bo'ladi, bu standart bo'lib Activity-ni qayta yaratadi. Composable ekranlarining holatini saqlash uchun oddiy ma'lumotlar uchun rememberSaveable yoki ekran doirasi bilan ViewModel dan foydalaning. Navigation Compose qayta yaratishdan so'ng back stack-ni tiklaydi, lekin composable() funksiyalari ichidagi holat rememberSaveable holda qayta o'rnatiladi.
Yo'q, composable() — faqat NavHost bloki ichida mavjud bo'lgan NavGraphBuilder kengaytma funksiyasidir. Navigatsiyasiz oddiy UI qismini almashtirish uchun shartli renderlash (when, if) yoki AnimatedContent dan foydalaning. composable() aynan orqaga stek va chuqur havolalarni qo'llab-quvvatlaydigan marshrutlash uchun mo'ljallangan.
ViewModel ichida SavedStateHandle dan foydalaning: birinchi o'tishda handle.get("initialized") null qaytaradi, qaytishda — saqlangan qiymatni. Shu bilan birga, navController.previousBackStackEntry orqali back stack-dagi joriy pozitsiyani tahlil qiling — null bo'lsa, bu navigatsiya stekidagi birinchi ekran.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.