Navigation Compose — کتابخانه Jetpack برای ناوبری اعلامی در برنامههای Android ساخته شده بر Jetpack Compose است. به جای FragmentManager یا ناوبری مبتنی بر Intent، Navigation Compose یک گراف مسیر یکپارچه ارائه میدهد که از طریق NavController و NavHost مدیریت میشود. بر اساس دادههای Google I/O (2025)، Navigation Compose روش توصیهشده ناوبری برای برنامههای Compose است که در بیش از 70% پروژههای جدید استفاده میشود. این کتابخانه از انتقال آرگومانهای تایپشده، لینکهای عمیق، انیمیشن انتقال و یکپارچهسازی با ViewModel از طریق SavedStateHandle پشتیبانی میکند.
نکات اصلی
Navigation Compose — کتابخانهای از مجموعه Jetpack است که چارچوب ناوبری برای برنامههای Compose فراهم میکند. این کتابخانه بر همان اصول Navigation Component برای سیستم View استوار است، اما با طبیعت اعلامی Compose سازگار شده است: به جای FragmentTransaction از توابع composable استفاده میشود و گراف ناوبری از طریق Kotlin DSL ساخته میشود.
تفاوت کلیدی Navigation Compose با ناوبری کلاسیک — عدم وجود FragmentManager است. هر صفحه یک تابع composable است که در NavHost هنگام تطابق مسیر رندر میشود. Back stack نه Fragment، بلکه یک رکورد با route، آرگومانها و وضعیت ذخیره میکند. این کار معماری را ساده میکند و تضادهای چرخه حیات مشخصه ناوبری Fragment را حذف میکند.
بر اساس دادههای Google (2025)، Navigation Compose مسیر experimental تا stable را طی کرده و از نسخه 2.8.0 بخشی از Jetpack است. این کتابخانه از Material3، Type-Safe Navigation (از طریق Kotlin Serialization)، گرافهای تو در تو و ماژولاریزاسیون پشتیبانی میکند. تنها محدودیت — عدم پشتیبانی از multi-back stack برای BottomNavigation بدون پیکربندی دستی است، اگرچه Google روی آن کار میکند.
معماری Navigation Compose حول سه موجودیت ساخته شده است: NavController (مدیریت پشته)، NavHost (کانتینر گراف) و NavDestination (مسیر جداگانه با composable). تعامل بین آنها اعلامی است: توسعهدهنده مسیرها و آرگومانها را توصیف میکند و کتابخانه وضعیتهای بارگذاری، ذخیره و بازیابی را مدیریت میکند.
NavController — عنصر مرکزی Navigation Compose است که پشته ناوبری را مدیریت میکند. از طریق rememberNavController() ایجاد میشود و به NavHost منتقل میشود. NavController back stack، نقطه ورود فعلی را ذخیره میکند و از اقدامات تأخیری (deeplink پس از مقداردهی گراف) پشتیبانی میکند.
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("profile/{userId}") { backStackEntry ->
ProfileScreen(
userId = backStackEntry.arguments?.getString("userId") ?: ""
)
}
}
}
روشهای اصلی NavController: navigate(route) — انتقال به مسیر، popBackStack() — بازگشت به صفحه قبلی، navigateAndClear(route) — انتقال با پاک کردن پشته. NavOptions رفتار را تعیین میکند: launchSingleTop از تکرار جلوگیری میکند، popUpTo پشته را تا مسیر مشخص شده پاک میکند، restoreState وضعیت قبلی را بازیابی میکند.
برای دسترسی به NavController از توابع composable تو در تو از NavHostController از طریق CompositionLocal استفاده کنید. LocalNavController در ScopedNavController داخل NavHost ارائه میشود. خارج از NavHost (مثلاً در BottomNavigation) کنترلر از طریق پارامترها یا ViewModel منتقل میشود.
NavHost — یک کانتینر composable است که NavController را به گراف مسیر متصل میکند. هر مسیر از طریق composable(route, arguments, deepLinks) اعلام میشود، جایی که route رشته مسیر با جاگرفتههای اختیاری {param} است. هنگام تطابق مسیر فعلی با route، NavHost بلوک composable مربوطه را رندر میکند.
گراف مسیر به صورت سلسلهمراتبی ساخته میشود: میتوان گرافها را از طریق navigation() برای گروهبندی مسیرها درون ماژول تو در تو قرار داد. گرافهای تو در تو startDestination خود را دارند و تحت یک پیشوند route مشترک ترکیب میشوند. این امکان سازماندهی معماری ماژولار را فراهم میکند، جایی که هر ماژول ویژگی زیرگراف خود را ثبت میکند.
NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") { MainScreen(navController) }
navigation(
route = "auth",
startDestination = "auth/login"
) {
composable("auth/login") { LoginScreen(navController) }
composable("auth/register") { RegisterScreen(navController) }
}
}
NavHost به طور خودکار دکمه بازگشت سیستم (back press) را از طریق LocalBackDispatcher مدیریت میکند. در Material3 Scaffold به طور پیشفرض NavController را برای عملکرد صحیح BottomNavigation دریافت میکند. NavHost composable را هنگام تغییر مسیر بازآفرینی میکند، اما وضعیت را از طریق rememberSaveable برای فیلدهای ورودی و اسکرول حفظ میکند.
Navigation Compose از انتقال آرگومانهای تایپشده بین صفحهها از طریق پارامترهای مسیر و NavType پشتیبانی میکند. پارامترها در route به صورت {paramName} با تعیین نوع از طریق arguments در composable() تعیین میشوند. NavType از String، Int، Long، Float، Boolean، Parcelable و Serializable پشتیبانی میکند.
| نوع آرگومان | NavType | مثال route |
|---|---|---|
| String | NavType.StringType | "profile/{name}" |
| Int | NavType.IntType | "item/{id}" |
| Boolean | NavType.BoolType | "settings?enabled={flag}" |
| Parcelable | NavType.ParcelableType | "details/{item}" |
| Float | NavType.FloatType | "map?lat={lat}&lng={lng}" |
آرگومانها از NavBackStackEntry از طریق arguments?.getType(key) استخراج میشوند. برای پارامترهای اجباری از defaultValue، برای اختیاری از nullable استفاده کنید. پشتیبانی Parcelable فقط با Kotlin Parcelize یا کتابخانه kotlinx.parcelize کار میکند. برای اشیاء پیچیده توصیه میشود ID را منتقل کرده و دادهها را از طریق ViewModel بارگذاری کنید، نه اینکه کل شیء را سریالسازی کنید.
از نسخه Navigation 2.8.0، Type-Safe Navigation با Kotlin Serialization در دسترس است: مسیرها به عنوان کلاسهای داده و آرگومانها به عنوان فیلد تعریف میشوند. این کار routeهای رشتهای را با اشیاء تایپشده جایگزین میکند و خطاهای نام مسیر را حذف میکند. برای مهاجرت به پلاگین Kotlin Serialization و وابستگی navigation-compose-typesafe نیاز است.
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
data object Home : ProfileRoute("home")
data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}
Deep Links — مکانیزم ناوبری است که امکان باز کردن یک صفحه خاص از برنامه را از طریق URL یا intent-filter فراهم میکند. در Navigation Compose لینکهای عمیق از طریق پارامتر deepLinks در composable() پیکربندی میشوند و هنگام تطابق URI با الگو به طور خودکار پردازش میشوند.
Deep Link به عنوان لیست UriPattern تعریف میشود: "https://example.com/profile/{userId}". پارامترهای URI به طور خودکار به آرگومانهای مسیر نگاشت میشوند. NavController لینک عمیق را هنگام راهاندازی برنامه (از طریق intent) و در حین کار (از طریق implicit deep links) پردازش میکند. برای پردازش لینکهای عمیق در انتظار از handleDeepLink() در NavController پس از مقداردهی گراف استفاده میشود.
به گفته Google، پیکربندی لینکهای عمیق برای موارد زیر توصیه میشود: اعلانهای فشار (Firebase Dynamic Links)، تأیید ایمیل، اشتراکگذاری محتوا و ناوبری از لینکهای وب. برای Android 12+ از Digital Asset Links برای تأیید اعتبار لینک عمیق استفاده میشود. AndroidManifest.xml باید intent-filter با autoVerify="true" برای باز کردن لینکها بدون دیالوگ داشته باشد.
composable(
route = "profile/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.StringType }),
deepLinks = listOf(
navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
)
) { backStackEntry ->
ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}
محدودیتهای لینکهای عمیق در Navigation Compose: کتابخانه از لینکهای عمیق معوق پشتیبانی نمیکند — لینک عمیق فقط پس از ساخت کامل گراف توسط NavHost پردازش میشود. اگر لینک عمیق قبل از مقداردهی گراف بیاید، باید آن را از طریق intent?.data به تعویق انداخته و در LaunchedEffect پردازش کرد. برای Firebase Dynamic Links از Firebase Dynamic Links SDK همراه با Navigation Compose استفاده کنید.
Navigation Compose از انیمیشن انتقال از طریق پارامترهای enterTransition، exitTransition، popEnterTransition و popExitTransition در composable() پشتیبانی میکند. انیمیشنها از طریق Compose Animation API پیادهسازی میشوند: fadeIn، slideInHorizontally، expandIn و غیره. به طور پیشفرض انیمیشن غیرفعال است — صفحهها بلافاصله جایگزین میشوند.
سناریوهای معمول انیمیشن: slideInHorizontally برای ناوبری به جلو (صفحه از راست وارد میشود)، slideOutHorizontally برای بازگشت (صفحه به راست خارج میشود). برای BottomNavigation بیشتر از انیمیشن fade بدون لغزش استفاده میشود. انیمیشنها از طریق NavHost تنظیم میشوند و اگر انیمیشنهای فردی مشخص نشده باشند، برای همه composable اعمال میشوند.
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally() + fadeIn() },
exitTransition = { slideOutHorizontally() + fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }
انیمیشنها را میتوان برای هر composable به صورت جداگانه با ارسال پارامترهای انیمیشن مستقیماً در composable() بازنویسی کرد. مهم: انیمیشنها نباید با انیمیشن سیستم دکمه بازگشت تداخل داشته باشند. برای shared element transition به کتابخانه accompanist-navigation-animation یا پیادهسازی سفارشی از طریق Modifier.graphicsLayer نیاز است. بر اساس Android Developers (2025)، 80% از برنامههای تولیدی از انیمیشن slide افقی برای ناوبری استاندارد استفاده میکنند.
سوالات متداول
Navigation Compose بدون Fragment کار میکند و از توابع composable و Kotlin DSL برای گراف استفاده میکند. Navigation Component (View) بر FragmentManager و گرافهای XML استوار است. نسخه Compose سادهتر، سریعتر است و چرخه حیات Fragment را ندارد. Navigation Component برای View فقط برای برنامههای هیبریدی مناسب است.
توصیه میشود ID شیء را منتقل کرده و دادهها را از طریق ViewModel با SavedStateHandle بارگذاری کنید. اگر شیء ساده است — از Parcelable از طریق kotlinx.parcelize استفاده کنید. انتقال اشیاء بزرگ به طور مستقیم از طریق آرگومانها (Bundle) به ~1 MB محدود است و میتواند باعث TransactionTooLargeException شود.
بله، از طریق تابع navigation(route, startDestination) درون NavHost. گرافهای تو در تو startDestination خود را دارند و تحت یک پیشوند route مشترک ترکیب میشوند. این امکان سازماندهی معماری ماژولار با گرافهای ایزوله برای هر ماژول ویژگی را فراهم میکند.
NavController به طور خودکار back press را از طریق BackHandler از Compose مدیریت میکند. هنگام فشار دادن دکمه بازگشت navController.popBackStack() را فراخوانی کنید. برای مدیریت سفارشی (تأیید خروج) از BackHandler(enabled = condition) { callback } قبل از فراخوانی popBackStack() استفاده کنید.
در حال حاضر Navigation Compose پشتیبانی نمیشود در Compose Multiplatform. برای بخش iOS پروژههای چندسکویی از Voyager یا Decompose استفاده کنید. Google روی پشتیبانی KMP کار میکند، اما تاریخ انتشار مشخصی ندارد. برای پروژههای Android-only، Navigation Compose تنها گزینه توصیهشده است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید