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

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

نظرة عامة

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

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

  • أنشئ وحدتَين فرعيتَين: 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()
    },
    // ...
)

استخدام ميزة "إدخال التبعية" لإضافة إدخالات إلى التطبيق الرئيسي

في مثال الرمز البرمجي السابق، يتم استدعاء كل أداة إنشاء إدخالات مباشرةً من خلال التطبيق الرئيسي باستخدام لغة DSL entryProvider. إذا كان تطبيقك يتضمّن العديد من الشاشات أو وحدات الميزات، قد لا يكون هذا الإجراء قابلاً للتوسّع بشكل جيد.

لحلّ هذه المشكلة، يجب أن يساهم كل وحدة ميزات في إنشاء أدوات إنشاء الإدخالات في نشاط التطبيق باستخدام ميزة "إدخال التبعية".

على سبيل المثال، يستخدم الرمز البرمجي التالي روابط متعددة في 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() }
                },
                // ...
            )
        }
    }
}

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

المراجع

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