নেভিগেশন কোড মডিউলারাইজ করা

এই পৃষ্ঠাটি আপনার নেভিগেশন কোড মডিউলারাইজ করার জন্য একটি গাইড। এটি সাধারণ অ্যাপ মডিউলারাইজেশন সংক্রান্ত নির্দেশিকার পরিপূরক হিসেবে কাজ করে।

এক নজরে

মডিউলারাইজ করা হল নেভিগেশন কোডকে আলাদা আলাদা মডিউলে ভাগ করার প্রক্রিয়া। এর মধ্যে রয়েছে সম্পর্কিত নেভিগেশন কী এবং সেগুলি যে কন্টেন্টকে প্রতিনিধিত্ব করে। এটি দায়িত্বের স্পষ্ট বিভাজন প্রদান করে এবং আপনার অ্যাপের বিভিন্ন ফিচারের মধ্যে নেভিগেট করতে দেয়।

আপনার নেভিগেশন কোড মডিউলারাইজ করতে, নিম্নলিখিত কাজগুলি করুন:

  • আপনার অ্যাপের প্রতিটি ফিচারের জন্য দুটি করে সাবমডিউল তৈরি করুন: api ও impl
  • প্রতিটি ফিচারের জন্য নেভিগেশন কী তার api মডিউলে রাখুন
  • প্রতিটি ফিচারের জন্য entryProviders ও নেভিগেট করা যায় এমন কন্টেন্ট সংশ্লিষ্ট impl মডিউলে রাখুন
  • আপনার মূল অ্যাপ মডিউলে entryProviders প্রদান করুন, সরাসরি অথবা ডিপেন্ডেন্সি ইনজেকশন ব্যবহার করে
তৈরি করার সময় সিন স্ট্র্যাটেজি ব্যবহার করতে পারে।

API ও প্রয়োগ সংক্রান্ত সাবমডিউলে আলাদা আলাদা ফিচার

আপনার অ্যাপের প্রতিটি ফিচারের জন্য, api ও impl নামের দুটি সাবমডিউল তৈরি করুন ("ইমপ্লিমেন্টেশন"-এর সংক্ষিপ্ত রূপ)। নেভিগেশন কোড কোথায় প্লেস করবেন তা ঠিক করতে নিচের টেবিল ব্যবহার করুন।

মডিউলের নাম

এর মধ্যে আছে

api

নেভিগেশন কী

impl

সেই ফিচারের কন্টেন্ট, যার মধ্যে NavEntry ও entryProvider-এর সংজ্ঞা পড়ে। এছাড়াও দেখুন কন্টেন্টের সাথে কী সম্পর্কিত সমস্যার সমাধান করা।

এই পদ্ধতিতে, একটি ফিচারের কন্টেন্ট, যা সেটির impl মডিউলে থাকে, তা অন্য মডিউলের নেভিগেশন কীয়ের উপর নির্ভর করে। এই মডিউলটি আবার সেই মডিউলের api মডিউলে থাকে।

ফিচার মডিউল নির্ভরতা ডায়াগ্রাম থেকে বোঝা যায় যে কীভাবে `impl` মডিউল `api` মডিউলের উপর নির্ভর করতে পারে।
ছবি ১. ফিচার মডিউল ডিপেন্ডেন্সি ডায়াগ্রাম, কীভাবে ইমপ্লিমেন্টেশন মডিউল API মডিউলের উপর নির্ভর করতে পারে তা দেখায়।

এক্সটেনশন ফাংশন ব্যবহার করে নেভিগেশন এন্ট্রি আলাদা করা

নেভিগেশন ৩-এ, নেভিগেশন এন্ট্রি ব্যবহার করে নেভিগেট করা যায় এমন কন্টেন্টকে সংজ্ঞায়িত করা হয়। এইসব এন্ট্রিকে আলাদা আলাদা মডিউলে আলাদা করতে, EntryProviderScope-এ এক্সটেনশন ফাংশন তৈরি করুন এবং সেই ফিচারের জন্য impl মডিউলে সেগুলি সরিয়ে দিন। এগুলিকে এন্ট্রি বিল্ডার বলা হয়।

নিচের কোডের উদাহরণে একটি এন্ট্রি বিল্ডার দেখানো হয়েছে যা দুটি নেভিগেশন এন্ট্রি তৈরি করে।

// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey

fun EntryProviderScope<NavKey>.featureAEntryBuilder() {
    entry<KeyA> {
        ContentRed("Screen A") {
            // Content for screen A
        }
    }
    entry<KeyA2> {
        ContentGreen("Screen A2") {
            // Content for screen A2
        }
    }
}

আপনার মূল অ্যাপ মডিউলে entryProvider ডিফাইন করার সময় entryProvider DSL ব্যবহার করে সেই ফাংশন কল করুন।

// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
NavDisplay(
    entryProvider = entryProvider {
        featureAEntryBuilder()
    },
    // ...
)

মূল অ্যাপে এন্ট্রি যোগ করতে ডিপেন্ডেন্সি ইনজেকশন ব্যবহার করা

আগের কোড উদাহরণে, প্রতিটি এন্ট্রি বিল্ডারকে entryProvider DSL ব্যবহার করে মূল অ্যাপ সরাসরি কল করে। আপনার অ্যাপে অনেক স্ক্রিন বা ফিচার মডিউল থাকলে, এই প্যাটার্নটি ভালোভাবে স্কেল নাও করতে পারে।

এটি সমাধান করতে, প্রতিটি ফিচার মডিউলকে ডিপেন্ডেন্সি ইনজেকশন ব্যবহার করে অ্যাপের অ্যাক্টিভিটিতে তার এন্ট্রি বিল্ডার কন্ট্রিবিউট করতে হবে।

যেমন, নিম্নলিখিত কোডটি Dagger মাল্টিবাইন্ডিং ব্যবহার করে, বিশেষ করে @IntoSet, Set-এর মালিকানাধীন MainActivity-এ এন্ট্রি বিল্ডার ইনজেক্ট করতে। এগুলিকে entryProvider-এর মধ্যে ইটারেটিভভাবে কল করা হয়, যার ফলে অসংখ্য এন্ট্রি বিল্ডার ফাংশনকে আলাদা করে কল করার প্রয়োজন হয় না।

ফিচার মডিউল

// import dagger.Module
// import dagger.Provides
// import dagger.hilt.InstallIn
// import dagger.hilt.android.components.ActivityRetainedComponent
// import dagger.multibindings.IntoSet

@Module
@InstallIn(ActivityRetainedComponent::class)
object FeatureAModule {

    @IntoSet
    @Provides
    fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = {
        featureAEntryBuilder()
    }
}

অ্যাপ মডিউল

// import android.os.Bundle
// import androidx.activity.ComponentActivity
// import androidx.activity.compose.setContent
// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey
// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
// import javax.inject.Inject

class MainActivity : ComponentActivity() {

    @Inject
    lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NavDisplay(
                entryProvider = entryProvider {
                    entryBuilders.forEach { builder -> this.builder() }
                },
                // ...
            )
        }
    }
}

আপনার নেভিগেশন এন্ট্রিকে যদি নেভিগেট করতে হয়—যেমন, সেটিতে এমন UI এলিমেন্ট আছে যা নতুন স্ক্রিনে নেভিগেট করে—তাহলে প্রতিটি বিল্ডার ফাংশনে অ্যাপের নেভিগেশন স্টেট পরিবর্তন করতে পারে এমন একটি অবজেক্ট ইনজেক্ট করুন।

আপনার অ্যাপে ডিপ লিঙ্ক কাজ করলে এবং সেটি মডিউলারাইজ করা হলে, প্রতিটি ফিচার মডিউলকে সেটির মালিকানাধীন গন্তব্যের জন্য DeepLinkMatcher ইনস্ট্যান্সকে ডিফাইন করতে হবে।

আপনার অ্যাপ জুড়ে সব ম্যাচিং একত্রিত করতে, আপনি ডিপেন্ডেন্সি ইনজেকশন মাল্টিবাইন্ডিং ব্যবহার করতে পারেন। যেমন, প্রতিটি ফিচার মডিউল ড্যাগারের @IntoSet মাল্টিবাইন্ডিংয়ে নিজের ম্যাচ করা কন্ট্রিবিউট করতে পারে:

ফিচার মডিউল

তারপরে, আপনার মূল অ্যাপ মডিউলে, যেমন আপনার MainActivity-এ, আপনি ম্যাচারদের সেট ইনজেক্ট করতে এবং ইনকামিং অনুরোধ ম্যাচ করার জন্য সেগুলি ব্যবহার করতে পারবেন:

অ্যাপ মডিউল

ডিপ লিঙ্ক নির্ধারণ ও ম্যানেজ করা সম্পর্কে আরও জানতে, ডিপ লিঙ্ক ব্যবহার করা দেখুন।

রিসোর্স

Navigation 3 কোড কীভাবে মডিউলারাইজ করতে হয় তা দেখানোর জন্য কোড স্যাম্পেল পেতে, এগুলি দেখুন: