ماژولار کردن کد ناوبری

این صفحه راهنمایی برای ماژولار کردن کد ناوبری شماست. این راهنما برای تکمیل راهنمایی‌های کلی برای ماژولار کردن برنامه در نظر گرفته شده است.

نمای کلی

ماژولار کردن کد ناوبری شما فرآیندی است که در آن کلیدهای ناوبری مرتبط و محتوایی که نمایش می‌دهند، به ماژول‌های جداگانه تفکیک می‌شوند. این کار تفکیک واضحی از مسئولیت‌ها را فراهم می‌کند و به شما امکان می‌دهد بین ویژگی‌های مختلف در برنامه خود پیمایش کنید.

برای ماژولار کردن کد ناوبری خود، موارد زیر را انجام دهید:

  • برای هر ویژگی در برنامه خود، دو زیرماژول ایجاد کنید: api و impl
  • کلیدهای ناوبری را برای هر ویژگی در ماژول api آن قرار دهید
  • entryProviders و محتوای قابل پیمایش را برای هر ویژگی در ماژول impl مرتبط قرار دهید.
  • ارائه entryProviders به ماژول‌های اصلی برنامه، چه به صورت مستقیم و چه با استفاده از تزریق وابستگی

ویژگی‌ها را به زیرماژول‌های API و پیاده‌سازی تفکیک کنید

برای هر ویژگی در برنامه خود، دو زیرماژول به نام‌های api و impl (مخفف "implementation") ایجاد کنید. از جدول زیر برای تعیین محل قرارگیری کد ناوبری استفاده کنید.

نام ماژول

شامل

api

کلیدهای ناوبری

impl

محتوای آن ویژگی، شامل تعاریف NavEntry ها و entryProvider . همچنین به resolve کلیدهای content مراجعه کنید.

این رویکرد به یک ویژگی اجازه می‌دهد تا با وابسته کردن محتوای آن، که در ماژول impl آن قرار دارد، به کلیدهای ناوبری ماژول دیگری که در ماژول api آن ماژول قرار دارد، به ویژگی دیگر هدایت شود.

نمودار وابستگی ماژول‌های ویژگی که نشان می‌دهد چگونه ماژول‌های «impl» می‌توانند به ماژول‌های «api» وابسته باشند.
شکل 1. نمودار وابستگی ماژول ویژگی که نشان می‌دهد چگونه ماژول‌های پیاده‌سازی می‌توانند به ماژول‌های 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 multibindings ، به طور خاص @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() }
                },
                // ...
            )
        }
    }
}

اگر ورودی‌های ناوبری شما نیاز به پیمایش دارند - برای مثال، حاوی عناصر رابط کاربری هستند که به صفحات جدید پیمایش می‌کنند - یک شیء که قادر به تغییر وضعیت ناوبری برنامه است را به هر تابع سازنده تزریق کنید.

منابع

برای نمونه‌های کدی که نحوه ماژول‌بندی کد Navigation 3 را نشان می‌دهند، به موارد زیر مراجعه کنید: