تقدّم هذه الصفحة دليلاً حول تقسيم رمز التنقّل إلى وحدات. وهي تهدف إلى استكمال الإرشادات العامة بشأن تقسيم التطبيقات إلى وحدات.
نظرة عامة
تجزئة رمز التنقّل هي عملية فصل مفاتيح التنقّل ذات الصلة والمحتوى الذي تمثله إلى وحدات فردية. يوفّر ذلك فصلًا واضحًا للمسؤوليات ويسمح لك بالتنقّل بين الميزات المختلفة في تطبيقك.
لتجزئة رمز التنقّل، اتّبِع الخطوات التالية:
- أنشئ وحدتَين فرعيتَين:
apiوimplلكل ميزة في تطبيقك - وضع مفاتيح التنقّل لكل ميزة في وحدة
apiالخاصة بها - وضع
entryProvidersوالمحتوى القابل للتصفّح لكل ميزة في وحدةimplالمرتبطة - قدِّم
entryProvidersإلى وحدات تطبيقك الرئيسية، إما مباشرةً أو باستخدام ميزة "إدخال التبعية".
فصل الميزات إلى وحدات فرعية خاصة بواجهة برمجة التطبيقات والتنفيذ
لكل ميزة في تطبيقك، أنشئ وحدتَين فرعيتَين باسمَي api وimpl (اختصارًا لكلمة "التنفيذ"). استخدِم الجدول التالي لتحديد مكان وضع رمز التنقّل.
اسم الوحدة |
يحتوي على |
|
|
|
محتوى هذه الميزة، بما في ذلك تعريفات |
يتيح هذا الأسلوب لإحدى الميزات الانتقال إلى ميزة أخرى من خلال السماح لمحتواها، المضمّن في وحدة 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 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:
وحدة الميزات
@Module @InstallIn(ActivityRetainedComponent::class) object FeatureADeepLinkModule { @IntoSet @Provides fun provideUserMatcher(): DeepLinkMatcher<*, *> { return UriDeepLinkMatcher( DeepLinkUri("www.example.com/users/{id}"), serializer<UserProfileKey>() ) } }
بعد ذلك، في وحدة تطبيقك الرئيسية، مثلاً في MainActivity، يمكنك إدخال مجموعة أدوات المطابقة واستخدامها لمطابقة الطلبات الواردة:
وحدة التطبيق
@AndroidEntryPoint class MainActivityWithDI : ComponentActivity() { @Inject lateinit var deepLinkMatchers: Set<@JvmSuppressWildcards DeepLinkMatcher<*, *>> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val request = DeepLinkRequest(intent = intent) val matchResult = deepLinkMatchers .mapNotNull { it.match(request) } .maxOrNull() val backStack = when (matchResult) { null -> listOf(HomeKey) is BackStackMatchResult<*, *> -> { @Suppress("UNCHECKED_CAST") matchResult.backStack as List<NavKey> } else -> listOf(matchResult.key) } } }
لمزيد من المعلومات حول تحديد الروابط لصفحات في التطبيق والتعامل معها، يُرجى الاطّلاع على إتاحة الروابط لصفحات في التطبيق.
الموارد
للاطّلاع على عيّنات التعليمات البرمجية التي توضّح كيفية تقسيم رمز Navigation 3 إلى وحدات، يُرجى الاطّلاع على:
- وصفات رموز بنية Navigation 3
- رحلة التعلّم حول تقسيم التطبيق إلى وحدات من تطبيق Now in Android
- Androidify