نقل بيانات التنقّل في Jetpack إلى التنقّل Compose

تتيح لك واجهة برمجة التطبيقات Navigation Compose التنقّل بين العناصر القابلة للإنشاء في تطبيق Compose، مع الاستفادة من مكوِّن Jetpack Navigation والبنية الأساسية والميزات.

توضّح هذه الصفحة كيفية نقل البيانات من Jetpack Navigation المستند إلى Fragment إلى Navigation Compose، وذلك كجزء من عملية نقل أكبر لواجهة المستخدم المستندة إلى View إلى Jetpack Compose.

المتطلبات الأساسية لنقل البيانات

يمكنك الانتقال إلى Navigation Compose بعد أن تتمكّن من استبدال جميع Fragments بعناصر واجهة مستخدم قابلة للإنشاء على الشاشة. يمكن أن تحتوي عناصر Compose القابلة للإنشاء على الشاشة على مزيج من محتوى Compose وView، ولكن يجب أن تكون جميع وجهات التنقّل عناصر قابلة للإنشاء لتفعيل عملية نقل Navigation Compose. وحتى ذلك الحين، عليك مواصلة استخدام مكوّن التنقّل المستند إلى Fragment في قاعدة الرموز البرمجية المتوافقة مع View وCompose. لمزيد من المعلومات، يمكنك الاطّلاع على مستندات التوافق التفاعلي مع أدوات التنقّل.

خطوات نقل البيانات

سواء كنت تتّبع استراتيجية نقل البيانات المقترَحة أو تتّخذ نهجًا آخر، ستصل إلى مرحلة تكون فيها جميع وجهات التنقّل عبارة عن عناصر واجهة مستخدم قابلة للإنشاء على الشاشة، مع عمل الفئات Fragment كحاويات قابلة للإنشاء فقط. في هذه المرحلة، يمكنك الانتقال إلى Navigation Compose.

إذا كان تطبيقك يتّبع نمط تصميم لوظائف المستخدم المحدّدة ودليلنا حول البنية، لن يتطلّب نقل التطبيق إلى Jetpack Compose وNavigation Compose إجراء عمليات إعادة تصميم كبيرة في الطبقات الأخرى من تطبيقك، باستثناء طبقة واجهة المستخدم.

للانتقال إلى Navigation Compose، اتّبِع الخطوات التالية:

  1. أضِف التبعية Navigation Compose إلى تطبيقك.
  2. أنشئ عنصر App-level قابل للإنشاء وأضِفه إلى Activity كنقطة دخول إلى Compose، مع استبدال عملية إعداد تصميم العرض:

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. أنشئ أنواعًا لكل وجهة تنقّل. استخدِم data object للمواقع التي لا تتطلّب أي بيانات، وdata class أو class للمواقع التي تتطلّب بيانات.

    @Serializable data object First
    @Serializable data class Second(val id: String)
    @Serializable data object Third
    

  4. اضبط NavController في مكان يمكن لجميع الدوال المركّبة التي تحتاج إلى الرجوع إليه الوصول إليه (يكون ذلك عادةً داخل الدالة المركّبة App). يتّبع هذا الأسلوب مبادئ نقل الحالة ويتيح لك استخدام NavController كمصدر موثوق للتنقّل بين الشاشات القابلة للإنشاء والحفاظ على سجلّ الرجوع:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  5. أنشئ NavHost تطبيقك داخل الدالة المركّبة App ومرِّر navController:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            // ...
        }
    }

  6. أضِف الوجهات composable لإنشاء الرسم البياني للتنقّل. إذا تم نقل كل شاشة سابقًا إلى Compose، ستتضمّن هذه الخطوة استخراج عناصر Compose الخاصة بالشاشة من الفئة Fragments إلى وجهات composable فقط:

    class FirstFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            return ComposeView(requireContext()).apply {
                setContent {
                    // FirstScreen(...) EXTRACT FROM HERE
                }
            }
        }
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            composable<First> {
                FirstScreen(/* ... */) // EXTRACT TO HERE
            }
            composable<Second> {
                SecondScreen(/* ... */)
            }
            // ...
        }
    }

  7. إذا اتّبعت الإرشادات الواردة في تصميم واجهة مستخدم Compose، خاصةً كيفية تمرير ViewModel وأحداث التنقّل إلى الدوال المركّبة، تكون الخطوة التالية هي تغيير طريقة توفير ViewModel لكل دالة مركّبة خاصة بالشاشة. يمكنك غالبًا استخدام ميزة &quot;إدخال Hilt&quot; ونقطة الدمج الخاصة بها مع Compose وNavigation من خلال hiltViewModel:

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  8. استبدِل جميع طلبات التنقّل findNavController() بطلبات navController، ومرِّر هذه الطلبات كأحداث تنقّل إلى كل شاشة قابلة للإنشاء، بدلاً من تمرير navController بالكامل. يتّبع هذا الأسلوب أفضل الممارسات في عرض الأحداث من الدوال المركّبة على المتصلين، ويحافظ على navController كمصدر وحيد للحقيقة.

    يمكن تمرير البيانات إلى وجهة من خلال إنشاء مثيل لفئة المسار المحدّدة لهذه الوجهة. ويمكن بعد ذلك الحصول على هذا المعرّف إما مباشرةً من إدخال سجلّ الأنشطة السابقة في الوجهة أو من ViewModel باستخدام SavedStateHandle.toRoute().

    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = First) {
            composable<First> {
                FirstScreen(
                    onButtonClick = {
                        // findNavController().navigate(firstScreenToSecondScreenAction)
                        navController.navigate(Second(id = "ABC"))
                    }
                )
            }
            composable<Second> { backStackEntry ->
                val secondRoute = backStackEntry.toRoute<Second>()
                SecondScreen(
                    id = secondRoute.id,
                    onIconClick = {
                        // findNavController().navigate(secondScreenToThirdScreenAction)
                        navController.navigate(Third)
                    }
                )
            }
            // ...
        }
    }

  9. أزِل جميع الفئات Fragment وتنسيقات XML ذات الصلة وعناصر التنقّل غير الضرورية والموارد الأخرى، بالإضافة إلى الاعتمادات القديمة على الفئة Fragment وJetpack Navigation.

يمكنك العثور على الخطوات نفسها مع المزيد من التفاصيل المتعلّقة بمكتبة Navigation Compose في مستندات الإعداد.

حالات الاستخدام الشائعة

بغض النظر عن مكوّن التنقّل الذي تستخدمه، تنطبق مبادئ التنقّل نفسها.

تشمل حالات الاستخدام الشائعة عند نقل البيانات ما يلي:

للحصول على معلومات أكثر تفصيلاً حول حالات الاستخدام هذه، يمكنك الاطّلاع على التنقّل باستخدام Compose.

استرداد البيانات المعقّدة عند التنقّل

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

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

القيود

يوضّح هذا القسم القيود الحالية على Navigation Compose.

نقل البيانات بشكل تدريجي إلى Navigation Compose

لا يمكنك حاليًا استخدام Navigation Compose مع الاستمرار في استخدام Fragments كوجهات في الرمز البرمجي. لبدء استخدام Navigation Compose، يجب أن تكون جميع وجهاتك قابلة للإنشاء. يمكنك تتبُّع طلب الميزة هذا على Issue Tracker.

الصور المتحركة للانتقال

بدءًا من الإصدار 2.7.0-alpha01 من Navigation، أصبح بإمكانك ضبط انتقالات مخصّصة مباشرةً في NavHost، بعد أن كان ذلك متاحًا سابقًا من خلال AnimatedNavHost. يمكنك الاطّلاع على ملاحظات الإصدار للحصول على مزيد من المعلومات.

مزيد من المعلومات

لمزيد من المعلومات حول الانتقال إلى Navigation Compose، يُرجى الاطّلاع على المراجع التالية:

  • الدرس التطبيقي حول ترميز Navigation Compose: تعرَّف على أساسيات Navigation Compose من خلال درس تطبيقي عملي.
  • مستودع Now in Android: تطبيق Android يعمل بكامل وظائفه تم إنشاؤه بالكامل باستخدام Kotlin وJetpack Compose، ويتّبع أفضل الممارسات في تصميم وتطوير تطبيقات Android ويتضمّن Navigation Compose.
  • نقل تطبيق Sunflower إلى Jetpack Compose: مشاركة مدوّنة توثّق عملية نقل تطبيق Sunflower النموذجي من Views إلى Compose، وتشمل أيضًا عملية النقل إلى Navigation Compose.
  • تطبيق Jetnews على كل شاشة: مشاركة مدوّنة توثّق عملية إعادة تصميم ونقل نموذج تطبيق Jetnews ليتوافق مع جميع الشاشات باستخدام Jetpack Compose وNavigation Compose.