Navigation Compose: ما هو، الهندسة المعمارية والعمل في التطوير

المؤلف: IT Sectr نُشر: 2026-06-29 وقت القراءة: 8 دق

Navigation Compose هي مكتبة Jetpack للتنقل التصريحي داخل تطبيقات Android المبنية على Jetpack Compose. بدلاً من FragmentManager أو التنقل القائم على Intent، تقدم Navigation Compose رسماً بيانياً واحداً للمسارات يُدار عبر NavController و NavHost. وفقاً لـ Google I/O (2025)، فإن Navigation Compose هي طريقة التنقل الموصى بها لتطبيقات Compose، المستخدمة في أكثر من 70% من المشاريع الجديدة. تدعم المكتبة تمرير الوسائط المكتوبة، والروابط العميقة، ورسوم الانتقال المتحركة، والتكامل مع ViewModel عبر SavedStateHandle.

النقاط الرئيسية

  • Navigation Compose — مكتبة Jetpack للتنقل التصريحي في Compose مع رسم بياني موحد للمسارات
  • NavController — وحدة التحكم المركزية التي تدير مكدس التنقل وحالة مكدس الرجوع
  • NavHost — حاوية تحدد الرسم البياني للمسارات عبر دوال composable مع المسار
  • الوسائط تُمرر عبر NavType و SavedStateHandle مع دعم المعلمات المكتوبة
  • الروابط العميقة — التنقل عبر عناوين URL خارجية مع تحليل تلقائي للوسائط من URI

ما هو Navigation Compose؟

Navigation Compose هي مكتبة من مجموعة Jetpack توفر إطار عمل للتنقل لتطبيقات Compose. تستند المكتبة إلى نفس مبادئ مكون التنقل لنظام View، لكنها مُكيَّفة مع الطبيعة التصريحية لـ Compose: بدلاً من FragmentTransaction، تُستخدم دوال composable، ويُبنى الرسم البياني للتنقل عبر Kotlin DSL.

الفرق الرئيسي بين Navigation Compose والتنقل الكلاسيكي هو غياب FragmentManager. كل شاشة هي دالة composable تُعرض في NavHost عندما يتطابق المسار. يخزن مكدس الرجوع ليس Fragment، بل سجلاً بالمسار والوسائط والحالة. هذا يبسط الهندسة المعمارية ويزيل تعارضات دورة الحياة النمطية للتنقل القائم على Fragment.

وفقاً لـ Google (2025)، انتقل Navigation Compose من المرحلة التجريبية إلى المستقرة وأصبح جزءاً من Jetpack منذ الإصدار 2.8.0. تدعم المكتبة Material3، والتنقل الآمن للأنواع (عبر Kotlin Serialization)، والرسوم البيانية المتداخلة، والنمطية. القيد الوحيد هو أن المكتبة لا تدعم مكدس الرجوع المتعدد لـ BottomNavigation دون تكوين يدوي، على الرغم من أن Google تعمل على ذلك.

تدور هندسة Navigation Compose حول ثلاثة كيانات: NavController (إدارة المكدس)، NavHost (حاوية الرسم البياني) و NavDestination (مسار فردي مع composable). التفاعل بينها تصريحي: يصف المطور المسارات والوسائط، وتتعامل المكتبة مع حالات التحميل والحفظ والاستعادة.

NavController هو العنصر المركزي في Navigation Compose، ويدير مكدس التنقل. يُنشأ عبر rememberNavController() ويُمرر إلى NavHost. يخزن NavController مكدس الرجوع، ونقطة الدخول الحالية، ويدعم الإجراءات المؤجلة (الرابط العميق بعد تهيئة الرسم البياني).

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("profile/{userId}") { backStackEntry ->
            ProfileScreen(
                userId = backStackEntry.arguments?.getString("userId") ?: ""
            )
        }
    }
}

الطرق الرئيسية لـ NavController: navigate(route) — الانتقال إلى مسار، popBackStack() — العودة إلى الشاشة السابقة، navigateAndClear(route) — الانتقال مع مسح المكدس. تحدد NavOptions السلوك: launchSingleTop يمنع التكرار، popUpTo يمسح المكدس حتى المسار المحدد، restoreState يستعيد الحالة السابقة.

للوصول إلى NavController من دوال composable المتداخلة بعمق، استخدم NavHostController عبر CompositionLocal. يتم توفير LocalNavController في ScopedNavController داخل NavHost. خارج NavHost (مثلاً، في BottomNavigation)، يتم تمرير وحدة التحكم عبر المعلمات أو ViewModel.

NavHost هي حاوية composable تربط NavController بالرسم البياني للمسارات. يُعلن كل مسار عبر composable(route, arguments, deepLinks)، حيث route هي سلسلة مسار مع عناصر نائبة {param} اختيارية. عندما يتطابق المسار الحالي، يعرض NavHost كتلة composable المقابلة.

يُبنى الرسم البياني للمسارات هرمياً: يمكن تداخل الرسوم البيانية عبر navigation() لتجميع المسارات داخل وحدة. الرسوم البيانية المتداخلة لها startDestination خاص بها وتُدمج تحت بادئة مسار مشتركة. هذا يسمح بتنظيم هندسة معيارية حيث تسجل كل وحدة ميزات رسمها البياني الفرعي الخاص بها.

kotlin
NavHost(
    navController = navController,
    startDestination = "main"
) {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

يتعامل NavHost تلقائياً مع زر الرجوع في النظام (back press) عبر LocalBackDispatcher. في Material3 Scaffold، يلتقط NavController افتراضياً للتشغيل الصحيح لـ BottomNavigation. يعيد NavHost إنشاء composable عند تغيير المسار، لكنه يحافظ على الحالة عبر rememberSaveable لحقول الإدخال والتمرير.

تمرير الوسائط بين الشاشات

يدعم Navigation Compose تمرير الوسائط المكتوبة بين الشاشات عبر معلمات المسار و NavType. تُحدد المعلمات في المسار كـ {paramName} مع تحديد النوع عبر arguments في composable(). يدعم NavType String، Int، Long، Float، Boolean، Parcelable و Serializable.

نوع الوسيطةNavTypeمثال المسار
StringNavType.StringType"profile/{name}"
IntNavType.IntType"item/{id}"
BooleanNavType.BoolType"settings?enabled={flag}"
ParcelableNavType.ParcelableType"details/{item}"
FloatNavType.FloatType"map?lat={lat}&lng={lng}"

تُستخرج الوسائط من NavBackStackEntry عبر arguments?.getType(key). للمعلمات الإجبارية استخدم defaultValue، للاختيارية — nullable. يعمل دعم Parcelable فقط مع Kotlin Parcelize أو مكتبة kotlinx.parcelize. للكائنات المعقدة، يُنصح بتمرير معرف وتحميل البيانات عبر ViewModel، بدلاً من تسلسل الكائن بأكمله.

منذ Navigation 2.8.0، تم تقديم التنقل الآمن للأنواع مع Kotlin Serialization: تُعرَّف المسارات كفئات بيانات، والوسائط كحقول. هذا يستبدل مسارات السلسلة بكائنات مكتوبة ويزيل الأخطاء في أسماء المسارات. يتطلب الترحيل مكون Kotlin Serialization الإضافي وتبعية navigation-compose-typesafe.

kotlin
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
    data object Home : ProfileRoute("home")
    data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}

الروابط العميقة هي آلية تنقل تسمح بفتح شاشة معينة من التطبيق عبر URL أو intent-filter. في Navigation Compose، تُكوَّن الروابط العميقة عبر معلمة deepLinks في composable() وتُعالج تلقائياً عندما يتطابق URI مع النمط.

يُحدد الرابط العميق كقائمة UriPattern: "https://example.com/profile/{userId}". تُعرَض معلمات URI تلقائياً على وسائط المسار. يعالج NavController الروابط العميقة عند بدء تشغيل التطبيق (عبر intent) وأثناء التشغيل (عبر الروابط العميقة الضمنية). لمعالجة الروابط العميقة المعلقة، استخدم handleDeepLink() في NavController بعد تهيئة الرسم البياني.

وفقاً لـ Google، يُوصى باستخدام الروابط العميقة لـ: الإشعارات (Firebase Dynamic Links)، والتحقق من البريد الإلكتروني، ومشاركة المحتوى، والتنقل الشامل من روابط الويب. لنظام Android 12+، تُستخدم Digital Asset Links للتحقق من سلطة الرابط العميق. يجب أن يحتوي AndroidManifest.xml على intent-filter مع autoVerify="true" لفتح الروابط دون حوار.

kotlin
composable(
    route = "profile/{userId}",
    arguments = listOf(navArgument("userId") { type = NavType.StringType }),
    deepLinks = listOf(
        navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
    )
) { backStackEntry ->
    ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}

قيود الروابط العميقة في Navigation Compose: المكتبة لا تدعم الروابط العميقة المؤجلة — تتم معالجة الرابط العميق فقط بعد أن يبني NavHost الرسم البياني بالكامل. إذا وصل رابط عميق قبل تهيئة الرسم البياني، فيجب تأجيله عبر intent?.data ومعالجته في LaunchedEffect. لـ Firebase Dynamic Links، استخدم Firebase Dynamic Links SDK مع Navigation Compose.

رسوم الانتقال المتحركة بين الشاشات

يدعم Navigation Compose رسوم الانتقال المتحركة عبر المعلمات enterTransition و exitTransition و popEnterTransition و popExitTransition في composable(). تُنفَّذ الرسوم المتحركة باستخدام Compose Animation API: fadeIn، slideInHorizontally، expandIn وغيرها. بشكل افتراضي، الرسوم المتحركة معطلة — تُستبدل الشاشات فوراً.

سيناريوهات الرسوم المتحركة النمطية: slideInHorizontally للتنقل للأمام (الشاشة تدخل من اليمين)، slideOutHorizontally للعودة (الشاشة تخرج إلى اليمين). لـ BottomNavigation، يُستخدم رسوم التلاشي بدون انزلاق بشكل أكثر شيوعاً. تُعيَّن الرسوم المتحركة عبر NavHost وتُطبق على جميع composables ما لم تُحدد رسوم فردية.

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally() + fadeIn() },
    exitTransition = { slideOutHorizontally() + fadeOut() },
    popEnterTransition = { fadeIn() },
    popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }

يمكن تجاوز الرسوم المتحركة لكل composable على حدة بتمرير معلمات الرسوم المتحركة مباشرة في composable(). من المهم ألا تتعارض الرسوم المتحركة مع رسوم الرجوع في النظام. لانتقال العناصر المشتركة، يلزم استخدام مكتبة accompanist-navigation-animation أو تطبيق مخصص عبر Modifier.graphicsLayer. وفقاً لـ Android Developers (2025)، 80% من التطبيقات الإنتاجية تستخدم الرسوم المتحركة الانزلاقية الأفقية للتنقل القياسي.

الأسئلة الشائعة

كيف يختلف Navigation Compose عن مكون التنقل لـ View؟

Navigation Compose يعمل بدون Fragment، مستخدماً دوال composable و Kotlin DSL للرسم البياني. مكون التنقل (View) يعتمد على FragmentManager ورسوم XML البيانية. إصدار Compose أبسط وأسرع وليس لديه دورات حياة Fragment. مكون التنقل لـ View مناسب فقط للتطبيقات الهجينة.

كيف تمرير كائن معقد بين الشاشات؟

يُوصى بتمرير معرف الكائن وتحميل البيانات عبر ViewModel مع SavedStateHandle. إذا كان الكائن بسيطاً، استخدم Parcelable عبر kotlinx.parcelize. تمرير الكائنات الكبيرة مباشرة عبر الوسائط (Bundle) محدود بحوالي 1 ميغابايت وقد يسبب TransactionTooLargeException.

هل يدعم Navigation Compose الرسوم البيانية المتداخلة؟

نعم، عبر الدالة navigation(route, startDestination) داخل NavHost. الرسوم البيانية المتداخلة لها startDestination خاص بها وتُدمج تحت بادئة مسار مشتركة. هذا يسمح بتنظيم هندسة معيارية برسوم بيانية معزولة لكل وحدة ميزات.

كيف معالجة زر الرجوع في النظام في Navigation Compose؟

يتعامل NavController تلقائياً مع الضغط على الرجوع عبر BackHandler من Compose. استدعِ navController.popBackStack() عند الضغط على رجوع. للمعالجة المخصصة (تأكيد الخروج)، استخدم BackHandler(enabled = condition) { callback } قبل استدعاء popBackStack().

هل يمكن استخدام Navigation Compose مع Jetpack Compose Multiplatform؟

حالياً، Navigation Compose غير مدعوم في Compose Multiplatform. للجزء الخاص بـ iOS من المشاريع عبر المنصات، استخدم Voyager أو Decompose. Google تعمل على دعم KMP، لكن لا يوجد جدول زمني للإصدار. للمشاريع التي تعمل بنظام Android فقط، Navigation Compose هو الخيار الوحيد الموصى به.

الملخص

  • Navigation Compose — مكتبة Jetpack للتنقل التصريحي في Compose، تعمل عبر رسم بياني للمسارات و NavController
  • NavController يدير مكدس الرجوع ويوفر طرق navigate، popBackStack للتنقل
  • NavHost يربط وحدة التحكم بالرسم البياني عبر composable()، ويدعم الرسوم البيانية المتداخلة للهندسة المعيارية
  • الوسائط تُمرر عبر NavType مع دعم String، Int، Parcelable والتنقل الآمن للأنواع مع Kotlin Serialization
  • الروابط العميقة تُكوَّن عبر navDeepLink مع UriPattern للتنقل الخارجي من عناوين URL والإشعارات
  • الرسوم المتحركة للانتقالات تُعيَّن عبر enterTransition، exitTransition باستخدام Compose Animation API
  • المكتبة لا تدعم KMP ولا مكدس الرجوع المتعدد لـ BottomNavigation دون تكوين إضافي

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا