تقسيم رمز التنقّل إلى وحدات

تقدّم هذه الصفحة دليلاً حول تقسيم رمز التنقّل إلى وحدات. وهي تهدف إلى استكمال الإرشادات العامة بشأن تقسيم التطبيقات إلى وحدات.

نظرة عامة

تجزئة رمز التنقّل هي عملية فصل مفاتيح التنقّل ذات الصلة والمحتوى الذي تمثله إلى وحدات فردية. يوفّر ذلك فصلًا واضحًا للمسؤوليات ويسمح لك بالتنقّل بين الميزات المختلفة في تطبيقك.

لتجزئة رمز التنقّل، اتّبِع الخطوات التالية:

  • أنشئ وحدتَين فرعيتَين: api وimpl لكل ميزة في تطبيقك
  • وضع مفاتيح التنقّل لكل ميزة في وحدة api الخاصة بها
  • وضع entryProviders والمحتوى القابل للتصفّح لكل ميزة في وحدة impl المرتبطة
  • قدِّم entryProviders إلى وحدات تطبيقك الرئيسية، إما مباشرةً أو باستخدام ميزة "إدخال التبعية".

فصل الميزات إلى وحدات فرعية خاصة بواجهة برمجة التطبيقات والتنفيذ

لكل ميزة في تطبيقك، أنشئ وحدتَين فرعيتَين باسمَي api وimpl (اختصارًا لكلمة "التنفيذ"). استخدِم الجدول التالي لتحديد مكان وضع رمز التنقّل.

اسم الوحدة

يحتوي على

api

مفاتيح التنقّل

impl

محتوى هذه الميزة، بما في ذلك تعريفات NavEntry وentryProvider راجِع أيضًا ربط المفاتيح بالمحتوى.

يتيح هذا الأسلوب لإحدى الميزات الانتقال إلى ميزة أخرى من خلال السماح لمحتواها، المضمّن في وحدة impl، بالاعتماد على مفاتيح التنقّل الخاصة بوحدة أخرى، مضمّنة في وحدة api الخاصة بهذه الوحدة.

مخطّط تبعية لوحدة الميزات يوضّح كيف يمكن لوحدات `impl` أن تعتمد على وحدات `api`.
الشكل 1. مخطّط تبعية لوحدة الميزات يوضّح كيف يمكن لوحدات التنفيذ أن تعتمد على وحدات واجهة برمجة التطبيقات.

فصل إدخالات التنقّل باستخدام دوال الإضافة

في 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 DSL عند تحديد entryProvider في وحدة تطبيقك الرئيسية.

// 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() }
                },
                // ...
            )
        }
    }
}

إذا كانت إدخالات التنقّل بحاجة إلى التنقّل، مثلاً إذا كانت تحتوي على عناصر واجهة مستخدم تنتقل إلى شاشات جديدة، يمكنك إدخال عنصر قادر على تعديل حالة التنقّل في التطبيق في كل دالة إنشاء.

إذا كان تطبيقك يتيح استخدام روابط لصفحات في التطبيق وكان مقسَّمًا إلى وحدات، يجب أن تحدّد كل وحدة ميزات مثيلات DeepLinkMatcher للوجهات التي تملكها.

لتجميع جميع أدوات المطابقة من تطبيقك، يمكنك استخدام عمليات الربط المتعددة لإدراج التبعيات. على سبيل المثال، يمكن لكل وحدة ميزات المساهمة في أدوات المطابقة الخاصة بها في @IntoSet multibinding في Dagger:

وحدة الميزات

بعد ذلك، في وحدة تطبيقك الرئيسية، مثلاً في MainActivity، يمكنك إدخال مجموعة أدوات المطابقة واستخدامها لمطابقة الطلبات الواردة:

وحدة التطبيق

لمزيد من المعلومات حول تحديد الروابط لصفحات في التطبيق والتعامل معها، يُرجى الاطّلاع على إتاحة الروابط لصفحات في التطبيق.

الموارد

للاطّلاع على عيّنات التعليمات البرمجية التي توضّح كيفية تقسيم رمز Navigation 3 إلى وحدات، يُرجى الاطّلاع على: