واحدبندی کردن کد پیمایش

این صفحه راهنمایی برای مدولار کردن کد پیمایش شما است. هدف از این راهنما، تکمیل راهنمای عمومی برای مدولارسازی برنامه است.

نمای کلی

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

برای مدولار کردن کد پیمایش، کارهای زیر را انجام دهید:

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

جدا کردن ویژگی‌ها به زیرماژول‌های api و پیاده‌سازی

برای هر ویژگی در برنامه‌تان، دو زیرواحد به‌نام‌های api و impl (مخفف «پیاده‌سازی») ایجاد کنید. از جدول زیر برای تصمیم‌گیری درباره محل قرار دادن کد پیمایش استفاده کنید.

نام واحد

حاوی

api

کلیدهای پیمایش

impl

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

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

نمودار وابستگی واحد ویژگی که نشان می‌دهد چگونه واحدهای `impl` می‌توانند
به واحدهای `api` وابسته باشند.
شکل ۱. نمودار وابستگی واحد ویژگی که نشان می‌دهد واحدهای پیاده‌سازی چگونه می‌توانند به واحدهای میانای برنامه‌سازی کاربردی وابسته باشند.

جدا کردن ورودی‌های پیمایش بااستفاده از توابع افزونه

در Navigation 3، محتوای قابل‌پیمایش بااستفاده از ورودی‌های پیمایش تعریف می‌شود. برای جدا کردن این ورودی‌ها به پیمانه‌های جداگانه، توابع افزونه را در 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() }
                },
                // ...
            )
        }
    }
}

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

اگر برنامه‌تان از پیوندهای عمیق پشتیبانی می‌کند و مدولار شده است، هر واحد ویژگی باید نمونه‌های DeepLinkMatcher را برای مقصدهایی که دارد تعریف کند.

برای گردآوری همه تطبیق‌دهنده‌ها از سراسر برنامه‌تان، می‌توانید از چنداتصالی تزریق وابستگی استفاده کنید. برای مثال، هر واحد ویژگی می‌تواند تطبیق‌دهنده‌های خود را به چنداتصالی Dagger @IntoSet اضافه کند:

واحد ویژگی

سپس، در ماژول اصلی برنامه‌تان، مثلاً در MainActivity، می‌توانید مجموعه تطبیق‌دهنده‌ها را تزریق کنید و از آن‌ها برای تطبیق درخواست‌های ورودی استفاده کنید:

واحد برنامه

برای اطلاعات بیشتر درباره تعریف و مدیریت پیوندهای عمیق، به پشتیبانی از پیوندهای عمیق مراجعه کنید.

منابع

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