নেভিগেশন কম্পোনেন্টটি জেটপ্যাক কম্পোজ অ্যাপ্লিকেশনগুলির জন্য সমর্থন প্রদান করে। নেভিগেশন কম্পোনেন্টের অবকাঠামো এবং বৈশিষ্ট্যগুলির সুবিধা গ্রহণ করে আপনি কম্পোজেবলগুলির মধ্যে নেভিগেট করতে পারেন।
কম্পোজের জন্য বিশেষভাবে নির্মিত সর্বশেষ আলফা নেভিগেশন লাইব্রেরির জন্য, নেভিগেশন 3 ডকুমেন্টেশন দেখুন।
সেটআপ
কম্পোজ সাপোর্ট করার জন্য, আপনার অ্যাপ মডিউলের build.gradle ফাইলে নিম্নলিখিত নির্ভরতা ব্যবহার করুন:
গ্রোভি
dependencies { def nav_version = "2.9.5" implementation "androidx.navigation:navigation-compose:$nav_version" }
কোটলিন
dependencies { val nav_version = "2.9.5" implementation("androidx.navigation:navigation-compose:$nav_version") }
শুরু করুন
কোনও অ্যাপে নেভিগেশন বাস্তবায়নের সময়, একটি নেভিগেশন হোস্ট, গ্রাফ এবং কন্ট্রোলার বাস্তবায়ন করুন। আরও তথ্যের জন্য, নেভিগেশন ওভারভিউ দেখুন।
একটি NavController তৈরি করুন
কম্পোজে কীভাবে একটি NavController তৈরি করবেন সে সম্পর্কে তথ্যের জন্য, Create a navigation controller এর কম্পোজ বিভাগটি দেখুন।
একটি NavHost তৈরি করুন
কম্পোজে কীভাবে একটি NavHost তৈরি করবেন সে সম্পর্কে তথ্যের জন্য, "আপনার নেভিগেশন গ্রাফ ডিজাইন করুন" এর কম্পোজ বিভাগটি দেখুন।
একটি কম্পোজেবলে নেভিগেট করুন
কম্পোজেবলে নেভিগেট করার তথ্যের জন্য, আর্কিটেকচার ডকুমেন্টেশনে " একটি গন্তব্যে নেভিগেট করুন" দেখুন।
আর্গুমেন্ট দিয়ে নেভিগেট করুন
কম্পোজেবল গন্তব্যস্থলের মধ্যে আর্গুমেন্ট পাস করার তথ্যের জন্য, আপনার নেভিগেশন গ্রাফ ডিজাইন করুন এর কম্পোজ বিভাগটি দেখুন।
নেভিগেট করার সময় জটিল তথ্য পুনরুদ্ধার করুন
নেভিগেট করার সময় জটিল ডেটা অবজেক্টের চারপাশে না যাওয়ার জন্য দৃঢ়ভাবে পরামর্শ দেওয়া হচ্ছে, বরং নেভিগেট করার সময় আর্গুমেন্ট হিসাবে ন্যূনতম প্রয়োজনীয় তথ্য, যেমন একটি অনন্য শনাক্তকারী বা আইডির অন্য রূপ, প্রেরণ করুন:
// Pass only the user ID when navigating to a new destination as argument
navController.navigate(Profile(id = "user1234"))
জটিল বস্তুগুলিকে সত্যের একক উৎসে, যেমন ডেটা স্তরে, ডেটা হিসেবে সংরক্ষণ করা উচিত। নেভিগেট করার পর আপনার গন্তব্যে পৌঁছানোর পর, আপনি পাস করা আইডি ব্যবহার করে সত্যের একক উৎস থেকে প্রয়োজনীয় তথ্য লোড করতে পারেন। ডেটা স্তর অ্যাক্সেস করার জন্য দায়ী আপনার ViewModel এ থাকা আর্গুমেন্টগুলি পুনরুদ্ধার করতে, ViewModel এর SavedStateHandle ব্যবহার করুন:
class UserViewModel(
savedStateHandle: SavedStateHandle,
private val userInfoRepository: UserInfoRepository
) : ViewModel() {
private val profile = savedStateHandle.toRoute<Profile>()
// Fetch the relevant user information from the data layer,
// ie. userInfoRepository, based on the passed userId argument
private val userInfo: Flow<UserInfo> = userInfoRepository.getUserInfo(profile.id)
// …
}
এই পদ্ধতিটি কনফিগারেশন পরিবর্তনের সময় ডেটা ক্ষতি রোধ করতে সাহায্য করে এবং প্রশ্নবিদ্ধ বস্তুটি আপডেট বা মিউটেশনের সময় যেকোনো অসঙ্গতি রোধ করে।
জটিল ডেটা কেন আর্গুমেন্ট হিসেবে প্রেরণ করা এড়িয়ে চলা উচিত, সেই বিষয়ে আরও বিস্তারিত ব্যাখ্যার জন্য, এবং সমর্থিত আর্গুমেন্টের ধরণগুলির একটি তালিকার জন্য, ডেস্টিনেশনের মধ্যে ডেটা পাস করুন দেখুন।
ডিপ লিঙ্ক
নেভিগেশন কম্পোজ ডিপ লিঙ্কগুলিকে সমর্থন করে যা composable() ফাংশনের অংশ হিসাবেও সংজ্ঞায়িত করা যেতে পারে। এর deepLinks প্যারামিটারটি NavDeepLink অবজেক্টের একটি তালিকা গ্রহণ করে যা navDeepLink() পদ্ধতি ব্যবহার করে দ্রুত তৈরি করা যেতে পারে:
@Serializable data class Profile(val id: String)
val uri = "https://www.example.com"
composable<Profile>(
deepLinks = listOf(
navDeepLink<Profile>(basePath = "$uri/profile")
)
) { backStackEntry ->
ProfileScreen(id = backStackEntry.toRoute<Profile>().id)
}
এই ডিপ লিঙ্কগুলি আপনাকে একটি নির্দিষ্ট URL, অ্যাকশন বা মাইম টাইপকে একটি কম্পোজেবলের সাথে সংযুক্ত করতে দেয়। ডিফল্টরূপে, এই ডিপ লিঙ্কগুলি বহিরাগত অ্যাপগুলিতে প্রকাশিত হয় না। এই ডিপ লিঙ্কগুলিকে বহিরাগতভাবে উপলব্ধ করার জন্য আপনাকে আপনার অ্যাপের manifest.xml ফাইলে উপযুক্ত <intent-filter> উপাদানগুলি যুক্ত করতে হবে। পূর্ববর্তী উদাহরণে ডিপ লিঙ্কটি সক্ষম করতে, আপনাকে ম্যানিফেস্টের <activity> উপাদানের ভিতরে নিম্নলিখিতটি যুক্ত করতে হবে:
<activity …>
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
</intent-filter>
</activity>
অন্য অ্যাপ দ্বারা ডিপ লিঙ্কটি ট্রিগার করা হলে নেভিগেশন স্বয়ংক্রিয়ভাবে সেই কম্পোজেবলে ডিপ লিঙ্কগুলিকে সংযুক্ত করে।
এই একই ডিপ লিঙ্কগুলি একটি কম্পোজেবল থেকে উপযুক্ত ডিপ লিঙ্ক ব্যবহার করে একটি PendingIntent তৈরি করতেও ব্যবহার করা যেতে পারে:
val id = "exampleId"
val context = LocalContext.current
val deepLinkIntent = Intent(
Intent.ACTION_VIEW,
"https://www.example.com/profile/$id".toUri(),
context,
MyActivity::class.java
)
val deepLinkPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(deepLinkIntent)
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
এরপর আপনি অন্যান্য PendingIntent মতো এই deepLinkPendingIntent ব্যবহার করে deep link গন্তব্যে আপনার অ্যাপটি খুলতে পারেন।
নেস্টেড নেভিগেশন
নেস্টেড নেভিগেশন গ্রাফ কীভাবে তৈরি করবেন সে সম্পর্কে তথ্যের জন্য, নেস্টেড গ্রাফ দেখুন।
একটি অভিযোজিত নীচের নেভিগেশন বার এবং নেভিগেশন রেল তৈরি করুন
আপনার অ্যাপটি যে WindowSizeClass এর মধ্যে রেন্ডার করা হয়েছে তার উপর ভিত্তি করে NavigationSuiteScaffold উপযুক্ত নেভিগেশন UI প্রদর্শন করে। কমপ্যাক্ট স্ক্রিনে, NavigationSuiteScaffold নীচের নেভিগেশন বার দেখায়; একটি প্রসারিত স্ক্রিনে, পরিবর্তে একটি নেভিগেশন রেল দেখানো হয়।
আরও তথ্যের জন্য বিল্ড অ্যাডাপ্টিভ নেভিগেশন দেখুন।
আন্তঃকার্যক্ষমতা
আপনি যদি কম্পোজের সাথে নেভিগেশন কম্পোনেন্ট ব্যবহার করতে চান, তাহলে আপনার কাছে দুটি বিকল্প আছে:
- টুকরোগুলির জন্য নেভিগেশন উপাদান ব্যবহার করে একটি নেভিগেশন গ্রাফ সংজ্ঞায়িত করুন।
- কম্পোজ ডেস্টিনেশন ব্যবহার করে কম্পোজে একটি
NavHostদিয়ে একটি নেভিগেশন গ্রাফ সংজ্ঞায়িত করুন। এটি কেবল তখনই সম্ভব যদি নেভিগেশন গ্রাফের সমস্ত স্ক্রিন কম্পোজেবল হয়।
অতএব, মিশ্র কম্পোজ এবং ভিউ অ্যাপগুলির জন্য সুপারিশ হল ফ্র্যাগমেন্ট-ভিত্তিক নেভিগেশন উপাদান ব্যবহার করা। ফ্র্যাগমেন্টগুলি তখন ভিউ-ভিত্তিক স্ক্রিন, কম্পোজ স্ক্রিন এবং ভিউ এবং কম্পোজ উভয় ব্যবহার করে এমন স্ক্রিন ধরে রাখবে। প্রতিটি ফ্র্যাগমেন্টের বিষয়বস্তু কম্পোজে আসার পরে, পরবর্তী পদক্ষেপ হল সমস্ত স্ক্রিনগুলিকে নেভিগেশন কম্পোজের সাথে সংযুক্ত করা এবং সমস্ত ফ্র্যাগমেন্টগুলি সরিয়ে ফেলা।
টুকরোগুলির জন্য নেভিগেশন সহ রচনা থেকে নেভিগেট করুন
কম্পোজ কোডের ভিতরে গন্তব্য পরিবর্তন করার জন্য, আপনি এমন ইভেন্টগুলি প্রকাশ করেন যা অনুক্রমের যেকোনো কম্পোজেবলে প্রেরণ এবং ট্রিগার করা যেতে পারে:
@Composable
fun MyScreen(onNavigate: (Int) -> Unit) {
Button(onClick = { onNavigate(R.id.nav_profile) } { /* ... */ }
}
আপনার ফ্র্যাগমেন্টে, আপনি NavController খুঁজে গন্তব্যে নেভিগেট করে কম্পোজ এবং ফ্র্যাগমেন্ট-ভিত্তিক নেভিগেশন কম্পোনেন্টের মধ্যে সেতুবন্ধন তৈরি করেন:
override fun onCreateView( /* ... */ ) {
setContent {
MyScreen(onNavigate = { dest -> findNavController().navigate(dest) })
}
}
বিকল্পভাবে, আপনি আপনার কম্পোজ অনুক্রমের নিচে NavController স্থানান্তর করতে পারেন। তবে, সহজ ফাংশনগুলি প্রকাশ করা অনেক বেশি পুনর্ব্যবহারযোগ্য এবং পরীক্ষাযোগ্য।
পরীক্ষামূলক
আপনার কম্পোজেবল গন্তব্যস্থল থেকে নেভিগেশন কোডকে আলাদা করুন যাতে প্রতিটি কম্পোজেবলকে NavHost কম্পোজেবল থেকে আলাদাভাবে পরীক্ষা করা যায়।
এর মানে হল, আপনার navController সরাসরি কোনও কম্পোজেবলে পাস করা উচিত নয় এবং এর পরিবর্তে প্যারামিটার হিসেবে নেভিগেশন কলব্যাক পাস করা উচিত। এটি আপনার সমস্ত কম্পোজেবলকে পৃথকভাবে পরীক্ষাযোগ্য করে তোলে, কারণ পরীক্ষায় navController এর কোনও উদাহরণের প্রয়োজন হয় না।
composable ল্যাম্বডা দ্বারা প্রদত্ত ইনডিরেক্টেশনের স্তর আপনাকে আপনার নেভিগেশন কোডকে কম্পোজেবল থেকে আলাদা করতে দেয়। এটি দুটি দিকে কাজ করে:
- আপনার কম্পোজেবলে শুধুমাত্র পার্স করা আর্গুমেন্টগুলি পাস করুন
- এমন ল্যাম্বডাস পাস করুন যা নেভিগেট করার জন্য কম্পোজেবল দ্বারা ট্রিগার করা উচিত,
NavControllerনিজেই নয়।
উদাহরণস্বরূপ, একটি ProfileScreen কম্পোজেবল যা একটি userId ইনপুট হিসেবে গ্রহণ করে এবং ব্যবহারকারীদের বন্ধুর প্রোফাইল পৃষ্ঠায় নেভিগেট করতে দেয়, তার স্বাক্ষর থাকতে পারে:
@Composable
fun ProfileScreen(
userId: String,
navigateToFriendProfile: (friendUserId: String) -> Unit
) {
…
}
এইভাবে, ProfileScreen কম্পোজেবল নেভিগেশন থেকে স্বাধীনভাবে কাজ করে, এটিকে স্বাধীনভাবে পরীক্ষা করার অনুমতি দেয়। composable ল্যাম্বডা নেভিগেশন API এবং আপনার কম্পোজেবলের মধ্যে ব্যবধান পূরণ করার জন্য প্রয়োজনীয় ন্যূনতম যুক্তিকে ধারণ করবে:
@Serializable data class Profile(id: String)
composable<Profile> { backStackEntry ->
val profile = backStackEntry.toRoute<Profile>()
ProfileScreen(userId = profile.id) { friendUserId ->
navController.navigate(route = Profile(id = friendUserId))
}
}
NavHost , আপনার কম্পোজেবল এবং আপনার ব্যক্তিগত স্ক্রিন কম্পোজেবলগুলিতে প্রেরিত নেভিগেশন অ্যাকশনগুলি পরীক্ষা করে আপনার অ্যাপ নেভিগেশন প্রয়োজনীয়তাগুলি কভার করে এমন পরীক্ষা লেখার পরামর্শ দেওয়া হচ্ছে।
NavHost পরীক্ষা করা হচ্ছে
আপনার NavHost পরীক্ষা শুরু করতে, নিম্নলিখিত নেভিগেশন-টেস্টিং নির্ভরতা যোগ করুন:
dependencies {
// ...
androidTestImplementation "androidx.navigation:navigation-testing:$navigationVersion"
// ...
}
আপনার অ্যাপের NavHost একটি কম্পোজেবলে মুড়ে দিন যা একটি NavHostController প্যারামিটার হিসেবে গ্রহণ করে।
@Composable
fun AppNavHost(navController: NavHostController){
NavHost(navController = navController){ ... }
}
এখন আপনি AppNavHost এবং NavHost ভিতরে সংজ্ঞায়িত সমস্ত নেভিগেশন লজিক পরীক্ষা করতে পারেন নেভিগেশন টেস্টিং আর্টিফ্যাক্ট TestNavHostController এর একটি উদাহরণ পাস করে। একটি UI পরীক্ষা যা আপনার অ্যাপ এবং NavHost এর শুরুর গন্তব্য যাচাই করে তা এইরকম দেখাবে:
class NavigationTest {
@get:Rule
val composeTestRule = createComposeRule()
lateinit var navController: TestNavHostController
@Before
fun setupAppNavHost() {
composeTestRule.setContent {
navController = TestNavHostController(LocalContext.current)
navController.navigatorProvider.addNavigator(ComposeNavigator())
AppNavHost(navController = navController)
}
}
// Unit test
@Test
fun appNavHost_verifyStartDestination() {
composeTestRule
.onNodeWithContentDescription("Start Screen")
.assertIsDisplayed()
}
}
নেভিগেশন অ্যাকশন পরীক্ষা করা হচ্ছে
আপনি আপনার নেভিগেশন বাস্তবায়ন একাধিক উপায়ে পরীক্ষা করতে পারেন, UI উপাদানগুলিতে ক্লিক করে এবং তারপর প্রদর্শিত গন্তব্য যাচাই করে অথবা বর্তমান রুটের সাথে প্রত্যাশিত রুটের তুলনা করে।
আপনার কংক্রিট অ্যাপের বাস্তবায়ন পরীক্ষা করার জন্য, UI-তে ক্লিক করাই ভালো। পৃথক কম্পোজেবল ফাংশনের পাশাপাশি এটি কীভাবে পরীক্ষা করতে হয় তা জানতে, Jetpack Compose কোডল্যাবে টেস্টিং দেখতে ভুলবেন না।
আপনি navController ব্যবহার করে আপনার দাবিগুলি পরীক্ষা করতে পারেন, বর্তমান রুটটি প্রত্যাশিত রুটের সাথে তুলনা করে, navController এর currentBackStackEntry ব্যবহার করে:
@Test
fun appNavHost_clickAllProfiles_navigateToProfiles() {
composeTestRule.onNodeWithContentDescription("All Profiles")
.performScrollTo()
.performClick()
assertTrue(navController.currentBackStackEntry?.destination?.hasRoute<Profile>() ?: false)
}
কম্পোজ পরীক্ষার মূল বিষয়গুলি সম্পর্কে আরও নির্দেশনার জন্য, আপনার কম্পোজ লেআউট পরীক্ষা করা এবং জেটপ্যাক কম্পোজ কোডল্যাবে পরীক্ষা করা দেখুন। নেভিগেশন কোডের উন্নত পরীক্ষা সম্পর্কে আরও জানতে, টেস্ট নেভিগেশন গাইডটি দেখুন।
আরও জানুন
জেটপ্যাক নেভিগেশন সম্পর্কে আরও জানতে, নেভিগেশন উপাদান দিয়ে শুরু করুন দেখুন অথবা জেটপ্যাক কম্পোজ নেভিগেশন কোডল্যাব নিন।
আপনার অ্যাপের নেভিগেশন কীভাবে ডিজাইন করবেন যাতে এটি বিভিন্ন স্ক্রিন সাইজ, ওরিয়েন্টেশন এবং ফর্ম ফ্যাক্টরের সাথে খাপ খাইয়ে নিতে পারে তা শিখতে, রেসপন্সিভ UI-এর জন্য নেভিগেশন দেখুন।
নেস্টেড গ্রাফ এবং বটম নেভিগেশন বার ইন্টিগ্রেশনের মতো ধারণা সহ একটি মডুলারাইজড অ্যাপে আরও উন্নত কম্পোজ নেভিগেশন বাস্তবায়ন সম্পর্কে জানতে, GitHub-এর Now in Android অ্যাপটি একবার দেখুন।
নমুনা
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়।
- কম্পোজে মেটেরিয়াল ডিজাইন ২
- জেটপ্যাক নেভিগেশনকে নেভিগেশন কম্পোজে স্থানান্তর করুন
- কোথায় উত্তোলন করতে হবে