NavController Navigation Compose لائبریری کا مرکزی جزو ہے، جو Android ایپلیکیشنز میں نیویگیشن اسٹیک اور back stack کی حالت کو منظم کرتا ہے۔ NavController کے ذریعے اسکرینوں کے درمیان منتقلی، پچھلے صفحات پر واپسی اور راستوں کے درمیان ڈیٹا کی منتقلی انجام دی جاتی ہے۔ Android Developers (2025) کے مطابق، NavController ایک سے زیادہ اسکرینوں والی کسی بھی Compose ایپلیکیشن کا لازمی عنصر ہے۔ کنٹرولر rememberNavController() کے ذریعے بنایا جاتا ہے، NavHost کو بھیجا جاتا ہے، اور کمپوزیشن کے کسی بھی مقام سے navigate() کال کرنے کے لیے دستیاب ہوتا ہے۔ بلٹ ان SavedStateHandle سپورٹ دوبارہ ترتیب دینے کے دوران خود بخود ViewModel کی حالت محفوظ کرتا ہے۔
اہم نکات
NavController Navigation Compose لائبریری کی ایک کلاس ہے جو Compose ایپلیکیشنز کے لیے نیویگیشن کنٹرولر لاگو کرتی ہے۔ NavController NavBackStackEntry اسٹیک کا نظم کرتا ہے، جہاں ہر اندراج میں راستہ، دلائل اور اسکرین کی حالت ہوتی ہے۔ کنٹرولر بنیادی نیویگیشن آپریشنز کو سپورٹ کرتا ہے: منتقلی، واپسی، تبدیلی اور صفائی۔
View سسٹم کے برعکس، جہاں نیویگیشن FragmentManager یا Intent کے ذریعے ہوتی تھی، NavController صرف Compose سیاق و سباق میں کام کرتا ہے۔ Back stack Fragment اسٹیک کی بجائے NavDestination گراف کے طور پر محفوظ کیا جاتا ہے۔ یہ Fragment بنانے اور ختم کرنے کے اوور ہیڈ کو ختم کرتا ہے اور جانچ کو آسان بناتا ہے — NavController کو TestNavHostController کے ذریعے موک کیا جا سکتا ہے۔
NavController کا NavHost سے گہرا تعلق ہے — ایک کنٹینر جو گراف سے موجودہ اسکرین رینڈر کرتا ہے۔ NavHost کے بغیر، NavController composable افعال ظاہر نہیں کر سکتا لیکن اسٹیک کو منظم کرنے کی صلاحیت برقرار رکھتا ہے۔ عام فن تعمیر میں، NavController Activity یا اہم composable سطح پر بنایا جاتا ہے اور پیرامیٹرز کے ذریعے کمپوزیشن ٹری میں نیچے بھیجا جاتا ہے۔
Google کے مطابق، NavController کئی بڑی ریلیز سے گزرا ہے۔ ورژن 2.8.0 نے Type-Safe Navigation شامل کیا، ورژن 2.9.0 نے predictive back gesture (Android 14+) کے لیے سپورٹ شامل کیا۔ کنٹرولر Material3 Scaffold اور BottomNavigation کے ساتھ مطابقت رکھتا ہے۔ ملٹی ماڈیول پروجیکٹس کے لیے، NavController DI (Hilt/Koin) یا کنسٹرکٹر پیرامیٹرز کے ذریعے بھیجا جاتا ہے۔
NavController composable فنکشن rememberNavController() کے ذریعے بنایا جاتا ہے۔ فنکشن موجودہ composable کی زندگی کے دور سے منسلک NavHostController (NavController کا ذیلی طبقہ) کی ایک مثال لوٹاتا ہے۔ کمپوزیشن چھوڑنے پر، کنٹرولر صاف ہو جاتا ہے۔ دوبارہ ترتیب دینے کے دوران کنٹرولر کو محفوظ رکھنے کے لیے، rememberSaveable یا ViewModel استعمال کریں۔
@Composable
fun MyApp() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") { MainScreen(navController) }
composable("details") { DetailsScreen(navController) }
}
}
NavController کی ترتیب میں شامل ہیں: NavHostController (اہم)، TestNavHostController (جانچ) اور ScopedNavController (اندرونی گراف کے لیے ذیلی)۔ BottomNavigation کے لیے، NavController پوری ایپ کے لیے واحد ہونا چاہیے — ہر ٹیب میں نیا کنٹرولر بنانے سے اسٹیک ختم ہو جائے گا۔ کنٹرولر کو اندرونی اسکرینوں پر بھیجنے کے لیے، پڑھنے کی اہلیت برقرار رکھنے کے لیے CompositionLocalProvider کی بجائے فنکشن پیرامیٹر استعمال کریں۔
نیویگیشن کی جانچ کے لیے compose-test-rule کے ساتھ TestNavHostController استعمال کریں۔ کنٹرولر ابتدائی راستہ سیٹ کرنے اور تصدیق کرنے کی اجازت دیتا ہے کہ navigate() نے متوقع منتقلی کو متحرک کیا۔ NavController کی جانچ کے لیے ایمولیٹر کی ضرورت نہیں — یہ Compose Test Semantics میچرز کے ساتھ کام کرتا ہے۔
navigate(route: String) طریقہ NavController میں بنیادی نیویگیشن میکانزم ہے۔ یہ ایک راستہ سٹرنگ، اختیاری NavOptions اور Navigator.Extras قبول کرتا ہے۔ NavOptions منتقلی کے رویے کو کنٹرول کرتے ہیں: launchSingleTop (اسٹیک میں راستہ نقل نہ کریں)، popUpTo (ایک راستے تک اسٹیک صاف کریں)، restoreState (پچھلی حالت بحال کریں)۔
NavOptions بلڈر نحو (NavOptionsBuilder) کے ذریعے سیٹ کیے جاتے ہیں۔ اہم پیرامیٹرز: popUpTo (راستہ + inclusive/saveState)، launchSingleTop (Boolean، true — نقل نہ بنائیں)، restoreState(واپسی پر حالت بحال کریں)۔ popUpTo کے بغیر، ہر navigate() اسٹیک میں ایک اندراج شامل کرتا ہے، جس سے back stack جمع ہوتا ہے اور Back بٹن کا غلط رویہ ہوتا ہے۔
navController.navigate("profile/42") {
popUpTo("main") { saveState = true }
launchSingleTop = true
restoreState = true
}
Navigator.Extras راستے کا حصہ نہ ہونے والے اضافی ڈیٹا (اینیمیشن کے لیے مشترکہ عناصر، Intent پرچم، Pac-Man بنڈل) بھیجنے کی اجازت دیتا ہے۔ Extras شاذ و نادر ہی استعمال ہوتے ہیں — بنیادی طور پر Accompanist Animation یا اپنی مرضی کے Navigator کے ساتھ انضمام کے لیے۔ زیادہ تر منظرناموں کے لیے، ایک راستہ سٹرنگ اور NavOptions کافی ہیں۔
popBackStack() پچھلی اسکرین پر واپسی کا طریقہ ہے۔ بغیر دلائل کے، یہ اسٹیک کی سب سے اوپر والی اندراج کو ہٹاتا ہے اور کامیابی پر true لوٹاتا ہے۔ اگر اسٹیک خالی ہے، طریقہ false لوٹاتا ہے اور Activity بند ہو جاتی ہے (super.onBackPressed() کی طرح)۔
اوور لوڈڈ ورژن popBackStack(route: String, inclusive: Boolean) مخصوص راستے تک تمام اندراجات کو ہٹاتا ہے۔ اگر inclusive = true ہے، تو مخصوص راستہ بھی ہٹا دیا جاتا ہے۔ طریقہ Boolean لوٹاتا ہے — اندراجات ملنے اور ہٹانے پر true۔ inclusive والا ورژن اختیار یا آرڈر مکمل کرنے کے بعد «روٹ اسکرین پر باہر نکلیں» منظرناموں کے لیے مفید ہے۔
| طریقہ | تفصیل | مثال |
|---|---|---|
| popBackStack() | ایک اسکرین پیچھے جائیں | navController.popBackStack() |
| popBackStack(route, false) | route تک صاف کریں (route رہتا ہے) | popBackStack(«home», false) |
| popBackStack(route, true) | route تک اور سمیت صاف کریں | popBackStack(«home», true) |
| navigate(route) { popUpTo(route) { inclusive = true } } | مکمل صفائی کے ساتھ جائیں | navigate(«login») { popUpTo(0) { inclusive = true } } |
سسٹم Back بٹن (ہارڈویئر بیک بٹن) کو ہینڈل کرنے کے لیے Compose کا BackHandler استعمال کریں۔ BackHandler enabled اور onBack قبول کرتا ہے — دبانے پر کال بیک۔ Android 14+ کے لیے، PredictiveBackGesture استعمال کیا جاتا ہے، جو NavController ورژن 2.9.0 سے مربوط ہے۔ Predictive back واپسی کا پیش نظارہ اینیمیشن شامل کرتا ہے۔
SavedStateHandle نیویگیشن اور دوبارہ ترتیب دینے کے دوران ViewModel کی حالت محفوظ رکھنے کا ایک میکانزم ہے۔ NavController ہر NavBackStackEntry کے لیے خود بخود SavedStateHandle فراہم کرتا ہے۔ SavedStateHandle کے ذریعے، ViewModel اسکرین کی حالت محفوظ کرتا ہے اور واپسی پر بحال کرتا ہے (restoreState = true)۔
Navigation Compose میں، SavedStateHandle ViewModel کے ساتھ استعمال ہوتا ہے: ViewModel SavedStateHandle کے ذریعے شروع کیا جاتا ہے، جو backStackEntry سے بھیجا جاتا ہے۔ دوسری اسکرین پر جا کر واپس آنے پر (restoreState کے ساتھ)، ViewModel نئے سرے سے بننے کی بجائے محفوظ کردہ حالت حاصل کرتا ہے۔ یہ ڈیٹا انپٹ، فلٹرز یا اسکرول والی اسکرینوں کے لیے اہم ہے۔
class ProfileViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
val userId: String = savedStateHandle.get<String>("userId") ?: ""
var searchQuery by savedStateHandle.getStateFlow("search", "")
.collectAsState()
}
SavedStateHandle قدیم اقسام، String، Bundle اور Parcelable کو سپورٹ کرتا ہے۔ پیچیدہ اشیاء کے لیے، صرف IDs محفوظ کریں اور کامل ڈیٹا ذخیرے سے لوڈ کریں۔ SavedStateHandle کی حد تقریباً 1 MB ہے، اس سے تجاوز کرنے پرTransactionTooLargeException ہوتا ہے۔ بڑی مقدار کے لیے، handle میں محفوظ کرنے کی بجائے Room یا DataStore استعمال کریں۔
اہم: SavedStateHandle صرف اس وقت حالت محفوظ رکھتا ہے جب NavOptions میں restoreState = true استعمال کیا جائے۔ اگر restoreState مخصوص نہیں ہے، تو واپسی پر ViewModel ڈیفالٹ اقدار کے ساتھ نئے سرے سے بنتا ہے۔ restoreState کے ساتھ BottomNavigation سوئچنگ کے لیے، NavController ہر ٹیب کی حالت محفوظ رکھتا ہے اور دوبارہ انتخاب پر بحال کرتا ہے۔
currentBackStackEntryAsState() ایک فنکشن ہے جو State<NavBackStackEntry?> لوٹاتا ہے، جو موجودہ راستے کی ہر تبدیلی پر اپ ڈیٹ ہوتا ہے۔ یہ نیویگیشن کے ساتھ UI ہم آہنگی کا بنیادی میکانزم ہے: BottomNavigation فعال آئٹم کو نمایاں کرتا ہے، Toolbar عنوان اپ ڈیٹ کرتا ہے، Drawer منتقلی پر بند ہوتا ہے۔
فنکشن snapshotFlow اور collectAsState کے ذریعے کام کرتا ہے: جب back stack تبدیل ہوتا ہے، Compose سبسکرائب کردہ عناصر کو دوبارہ کمپوز کرتا ہے۔ اہم: currentBackStackEntryAsState() صرف منتقلی اینیمیشن مکمل ہونے کے بعد اپ ڈیٹ ہوتا ہے۔ فوری اپ ڈیٹس کے لیے، currentDestination استعمال کریں، جو navigate() کے ساتھ ہم وقت تبدیل ہوتا ہے لیکن حالت کو سپورٹ نہیں کرتا۔
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
Text(
text = when (currentRoute) {
"home" -> "Home"
"profile" -> "Profile"
else -> ""
}
)
موجودہ راستے کے دلائل تک رسائی کے لیے navBackStackEntry?.arguments استعمال کریں۔ یہ BottomNavigation میں آسان ہے: selectedItem کا حساب currentRoute کی بنیاد پر کیا جاتا ہے۔ نیویگیشن ڈیبگنگ کے لیے NavController.addOnDestinationChangedListener() استعمال کریں جو ہر منتقلی کو لاگ کرتا ہے۔ پروڈکشن میں، بڑی تعداد میں composable کے اندر سبسکرپشنز سے بچیں — ViewModel میں ایک واحد ذریعہ بنائیں اور State کو UI میں بھیجیں۔
اکثر پوچھے گئے سوالات
تکنیکی طور پر ہاں، لیکن سفارش نہیں کی جاتی۔ ایک واحد NavController مستقل back stack کو یقینی بناتا ہے اور ڈیبگنگ کو آسان بناتا ہے۔ متعدد کنٹرولر صرف علیحدہ نیویگیشن والے اندرونی گراف کے لیے جائز ہیں (مثال کے طور پر، اپنے اسٹیک والا modal bottom sheet)۔
NavController کو ViewModel میں کنسٹرکٹر یا DI کے ذریعے بھیجیں۔ تاہم، NavController خود بھیجنے کی بجائے صرف کال بیک فنکشنز (onNavigate, onBack) بھیجنا بہتر ہے — یہ جانچ کو آسان بناتا ہے۔ ایونٹس کے لیے، ViewModel میں Channel<NavEvent> استعمال کریں اور UI میں جمع کریں۔
مسئلہ زندگی کے دور میں ہے: اگر NavController ابھی شروع نہیں ہوا (NavHost نہیں بنا)، navigate() نظر انداز کیا جاتا ہے۔ ڈیٹا لوڈ کرنے کے بعد نیویگیشن کال کرنے کے لیے LaunchedEffect استعمال کریں، صوابدیدی زندگی کے دور والے coroutine کے اندر نہیں۔
navController.navigate(«target») { popUpTo(0) { inclusive = true } } کال کریں۔ popUpTo(0) پیرامیٹر اسٹیک کو مکمل طور پر صاف کرتا ہے، inclusive = true ابتدائی اندراج کو بھی ہٹاتا ہے۔ launchSingleTop = true پرچم نقل راستوں کو روکتا ہے۔
NavHostController NavController کا ایک ذیلی طبقہ ہے جس میں NavHost کے لیے اضافی طریقے ہیں (مثال کے طور پر، setOnBackStackChangedListener)۔ NavController بنیادی طبقہ ہے جو NavHost کے باہر پروگرامی اسٹیک نظم کے لیے استعمال کیا جا سکتا ہے۔ زیادہ تر صورتوں میں، NavHostController استعمال کیا جاتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں