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 builder সিনট্যাক্সের মাধ্যমে সেট করা হয়: 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 বাটন (hardware back button) হ্যান্ডেল করতে, 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 সমর্থন করে। জটিল অবজেক্টের জন্য, শুধুমাত্র ID সংরক্ষণ করুন এবং রিপোজিটরি থেকে সম্পূর্ণ ডেটা লোড করুন। 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-এ একটি একক উৎস তৈরি করুন এবং UI-তে State পাঠান।
সচরাচর জিজ্ঞাসিত প্রশ্ন
প্রযুক্তিগতভাবে হ্যাঁ, তবে সুপারিশ করা হয় না। একক NavController ধারাবাহিক back stack নিশ্চিত করে এবং ডিবাগিং সহজ করে। একাধিক কন্ট্রোলার শুধুমাত্র পৃথক নেভিগেশন সহ নেস্টেড গ্রাফের জন্য ন্যায়সঙ্গত (উদাহরণস্বরূপ, নিজস্ব স্ট্যাক সহ modal bottom sheet)।
কনস্ট্রাক্টর বা DI-এর মাধ্যমে ViewModel-এ NavController পাঠান। তবে, 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন