يتيح لك التنقل إرفاق البيانات بعملية التنقل من خلال تحديد الوسيطات الخاصة بوجهة معيّنة على سبيل المثال، قد تأخذ وجهة الملف الشخصي للمستخدم رقم تعريف المستخدم. لتحديد المستخدم الذي سيتم عرضه.
بشكلٍ عام، يجب أن تفضّل بشدة تمرير أقل قدر من البيانات
بين الوجهات. على سبيل المثال، يجب تمرير مفتاح لاسترداد كائن
بدلاً من تمرير الكائن نفسه، كمساحة إجمالية لجميع الحالات المحفوظة
متاحة فقط على Android. إذا كنت بحاجة إلى تمرير كميات كبيرة من البيانات، فاستخدم
ViewModel
كما هو موضّح في
نظرة عامة على ViewModel.
تحديد وسيطات الوجهة
لتمرير البيانات بين الوجهات، حدد أولاً الوسيطة بإضافتها إلى الوجهة التي تستلمها باتّباع الخطوات التالية:
- في محرر التنقل، انقر على الوجهة التي تتلقّى الوسيطة.
- في لوحة السمات، انقر على إضافة (+).
- في نافذة إضافة رابط وسيطة التي تظهر، أدخِل اسم الوسيطة. ونوع الوسيطة، وما إذا كانت الوسيطة قابلة للقيم الفارغة، وقيمة تلقائية، إذا احتاجت.
- انقر على إضافة. لاحظ أن الوسيطة تظهر الآن في الوسيطات في لوحة السمات.
- بعد ذلك، انقر على الإجراء المقابل الذي ينقلك إلى هذه الوجهة. في لوحة السمات، من المفترض أن تظهر لك الآن الوسيطة التي تمت إضافتها حديثًا. في قسم القيم التلقائية للوسيطات.
ويتبيّن لك أيضًا أنّه تمت إضافة الوسيطة في XML. انقر على علامة التبويب النص. للتبديل إلى عرض XML، وستلاحظ أنه تمت إضافة الوسيطة إلى التي تتلقى الوسيطة. يتم عرض مثال في ما يلي:
<fragment android:id="@+id/myFragment" > <argument android:name="myArg" app:argType="integer" android:defaultValue="0" /> </fragment>
أنواع الوسيطات المتوافقة
تتيح مكتبة التنقّل استخدام أنواع الوسيطات التالية:
النوع | بنية app:argType | دعم القيم التلقائية | تتم المعالجة في المسارات | قابلة للإلغاء |
---|---|---|---|---|
عدد صحيح | app:argType="integer" | نعم | نعم | لا |
نافذة عائمة | app:argType="float" | نعم | نعم | لا |
الصيغة الطويلة | app:argType="long" | نعم، يجب أن تنتهي القيم التلقائية دائمًا بحرف L لاحقة (مثلاً "123L"). | نعم | لا |
منطقي | app:argType="boolean" | نعم - "صحيح" أو "خطأ" | نعم | لا |
سلسلة | app:argType="string" | نعم | نعم | نعم |
مرجع الموارد | app:argType="reference" | نعم، يجب أن تكون القيم التلقائية على شكل " @resourceType/resourceName". (مثل " @style/myCustomStyle") أو "0" | نعم | لا |
قطع مخصّصة | app:argType="<type>", حيث <type> هو اسم الفئة المؤهلة بالكامل من Parcelable |
تدعم القيمة التلقائية " @null". لا تتيح استخدام القيم التلقائية الأخرى. | لا | نعم |
مخصّص للتسلسل | app:argType="<type>", حيث <type> هو اسم الفئة المؤهلة بالكامل من Serializable |
تدعم القيمة التلقائية " @null". لا تتيح استخدام القيم التلقائية الأخرى. | لا | نعم |
تعداد مخصص | app:argType="<type>", حيث <type> هو الاسم المؤهّل بالكامل للتعداد | نعم - يجب أن تتطابق القيم التلقائية مع الاسم غير المؤهل (مثل "Success" لمطابقة MyEnum.Success). | لا | لا |
إذا كان نوع الوسيطة يتوافق مع القيم الفارغة، يمكنك الإعلان عن قيمة تلقائية
خالية باستخدام android:defaultValue="@null"
.
يمكن تحليل المسارات والروابط المؤدية إلى صفحات في التطبيق ومعرّفات الموارد المنتظمة (URI) مع وسيطاتها من السلاسل. لا يمكن ذلك باستخدام أنواع بيانات مخصّصة مثل قطع الأراضي قابلة للتسلسل كما هو موضح في الجدول السابق. لتمرير البيانات المعقدة والمخصصة، قم بتخزين البيانات في مكان آخر مثل ViewModel أو قاعدة البيانات وتمرير المعرف فقط أثناء التنقل ثم استرداد البيانات في الموقع الجديد بعد انتهاء التنقل.
عند اختيار أحد الأنواع المخصَّصة، يظهر مربّع الحوار اختيار صف يطلب منك اختيار الفئة المناسبة لهذا النوع. علامة التبويب المشروع تتيح لك اختيار فئة من مشروعك الحالي.
يمكنك اختيار <inferred type> للحصول على مكتبة التنقّل. تحدد النوع بناءً على القيمة المقدمة.
يمكنك تحديد مصفوفة للإشارة إلى أن الوسيطة يجب أن تكون صفيفًا من قيمة النوع المحدّدة. ملاحظات:
- لا يمكن استخدام مصفوفة من التعدادات وصفائف مراجع الموارد.
- تسمح المصفوفات بالقيم القابلة للقيم الفارغة، بصرف النظر عن دعم القيم القابلة للقيم الفارغة
وقيم النوع الأساسي. على سبيل المثال، استخدام
يتيح لك
app:argType="integer[]"
استخدامapp:nullable="true"
الإشارة إلى أن تمرير صفيفة خالية أمر مقبول. - تتيح الصفائف قيمة تلقائية واحدة، وهي " @null". لا تدعم الصفائف أيًا قيمة افتراضية أخرى.
إلغاء وسيطة وجهة في إجراء
ويتم استخدام الوسيطات على مستوى الوجهة والقيم الافتراضية من خلال كل الإجراءات التي الانتقال إلى الوجهة. إذا لزم الأمر، يمكنك إلغاء القيمة الافتراضية (أو قم بتعيين واحدة إذا لم تكن موجودة بالفعل) عن طريق تحديد وسيطة في مستوى الإجراء. يجب أن تكون هذه الوسيطة من نفس الاسم والنوع كوسيطة. الواردة في الوجهة.
يُعلِن ملف XML التالي عن إجراء يتضمّن وسيطة تلغي وسيطة على مستوى الوجهة من المثال السابق:
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
استخدام "الوسيطات الآمنة" لتمرير البيانات مع الحفاظ على أمان النوع
يشتمل مكوِّن التنقل على مكون إضافي لنظام Gradle يسمى "الوسيطات الآمنة" التي تنشئ فئات الكائنات البسيطة ومنصات الإنشاء للتنقل الآمن من ناحية النوع والوصول إلى أي الوسيطات المرتبطة. يوصى بشدة باستخدام الوسيطات الآمنة للتنقل وتمرير البيانات، لأنها تضمن أمان الكتابة.
إذا كنت لا تستخدم Gradle، فلا يمكنك استخدام المكوّن الإضافي Args. وفي هذه الحالات، يمكنك استخدام الحِزم لإجراء وتمرير البيانات.
لإضافة الوسيطات الآمنة
إلى مشروعك، عليك تضمين classpath
التالي في ملف build.gradle
ذي المستوى الأعلى:
Groovy
buildscript { repositories { google() } dependencies { def nav_version = "2.8.0" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" } }
Kotlin
buildscript { repositories { google() } dependencies { val nav_version = "2.8.0" classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version") } }
ويجب أيضًا تطبيق أحد المكوّنات الإضافية المتاحة.
لإنشاء رمز لغة Java بشكل مناسب لوحدات Java أو وحدات Java أو Kotlin المختلطة، أضف
هذا السطر إلى ملف build.gradle
الخاص بالتطبيق أو الوحدة:
Groovy
plugins { id 'androidx.navigation.safeargs' }
Kotlin
plugins { id("androidx.navigation.safeargs") }
وبدلاً من ذلك، يمكنك إضافة ما يلي لإنشاء رمز Kotlin المناسب للوحدات التي تعمل بلغة Kotlin فقط:
Groovy
plugins { id 'androidx.navigation.safeargs.kotlin' }
Kotlin
plugins { id("androidx.navigation.safeargs.kotlin") }
يجب أن يكون لديك android.useAndroidX=true
في
ملف واحد (gradle.properties
) وفقًا لما ورد في
نقل البيانات إلى AndroidX
بعد تفعيل الوسيطات الآمنة، يحتوي الرمز الذي أنشأته على ما يلي: اكتب فئات وطرقًا آمنة لكل إجراء وكذلك مع كل عملية إرسال وجهة الاستلام.
يتمّ إنشاء فئة لكلّ وجهة ينشأ فيها الإجراء. الاسم في هذه الفئة هو اسم الوجهة الأصلية ملحقة بـ كلمة "الاتجاهات". على سبيل المثال، إذا كانت الوجهة الأصلية جزءًا التي تحمل اسم
SpecifyAmountFragment
، تُسمى الفئة التي تم إنشاؤهاSpecifyAmountFragmentDirections
تشتمل هذه الفئة على طريقة لكل إجراء محدد في علامة الوجهة.
يتم إنشاء فئة داخلية لكل إجراء يتم استخدامه لتمرير الوسيطة، اسم مستند إلى الإجراء. على سبيل المثال، إذا كان الإجراء يسمى
confirmationAction,
اسم الصف هوConfirmationAction
. إذا كان يحتوي الإجراء على وسيطات بدونdefaultValue
، فأنت تستخدم فئة الإجراءات المرتبطة لتعيين قيمة الوسيطات.يتمّ إنشاء فئة للوجهة المستلِمة. اسم هذا الفئة هو يتم إلحاق اسم الوجهة بالكلمة "Args". على سبيل المثال، إذا يُطلق على الجزء الوجهة اسم
ConfirmationFragment,
. العنصر الذي تم إنشاؤه تسمى الصفConfirmationFragmentArgs
. استخدامfromBundle()
لهذا الصف لاسترداد الوسيطات.
يوضح المثال التالي كيفية استخدام هذه الطرق لتعيين وسيطة
تمريره إلى navigate()
:
Kotlin
override fun onClick(v: View) { val amountTv: EditText = view!!.findViewById(R.id.editTextAmount) val amount = amountTv.text.toString().toInt() val action = SpecifyAmountFragmentDirections.confirmationAction(amount) v.findNavController().navigate(action) }
Java
@Override public void onClick(View view) { EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount); int amount = Integer.parseInt(amountTv.getText().toString()); ConfirmationAction action = SpecifyAmountFragmentDirections.confirmationAction(); action.setAmount(amount); Navigation.findNavController(view).navigate(action); }
في رمز وجهة الاستلام، استخدِم الطريقة getArguments()
.
لاسترداد الحزمة واستخدام محتواها. وعند استخدام تبعيات -ktx
،
يمكن لمستخدمي Kotlin أيضًا استخدام تفويض السمة by navArgs()
للوصول إلى البيانات.
الوسيطة.
Kotlin
val args: ConfirmationFragmentArgs by navArgs() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { val tv: TextView = view.findViewById(R.id.textViewAmount) val amount = args.amount tv.text = amount.toString() }
Java
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { TextView tv = view.findViewById(R.id.textViewAmount); int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount(); tv.setText(amount + ""); }
استخدام الوسيطات الآمنة مع إجراء عام
عند استخدام الوسيطات الآمنة مع
الإجراء العام،
يجب توفير القيمة android:id
للعنصر <navigation>
الجذر، حيث
كما هو موضح في المثال التالي:
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_nav" app:startDestination="@id/mainFragment"> ... </navigation>
يؤدّي التنقّل إلى إنشاء فئة Directions
للعنصر <navigation>
الذي يكون
استنادًا إلى القيمة android:id
. على سبيل المثال، إذا كان لديك <navigation>
العنصر android:id=@+id/main_nav
، تُسمى الفئة التي تم إنشاؤها
MainNavDirections
تحتوي جميع الوجهات ضمن العنصر <navigation>
على
التي تم إنشاؤها للوصول إلى جميع الإجراءات العامة المرتبطة باستخدام
الطرق كما هو موضح في القسم السابق.
تمرير البيانات بين الوجهات باستخدام كائنات الحزمة
إذا كنت لا تستخدم Gradle، فلا يزال بإمكانك تمرير الوسيطات بين الوجهات
باستخدام كائنات Bundle
. أنشِئ كائن Bundle
وأرسِله إلى الوجهة.
باستخدام navigate()
، كما في المثال التالي:
Kotlin
val bundle = bundleOf("amount" to amount) view.findNavController().navigate(R.id.confirmationAction, bundle)
Java
Bundle bundle = new Bundle(); bundle.putString("amount", amount); Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);
في رمز وجهة الاستلام، استخدِم الطريقة getArguments()
من أجل
استرداد Bundle
واستخدام محتواه:
Kotlin
val tv = view.findViewById<TextView>(R.id.textViewAmount) tv.text = arguments?.getString("amount")
Java
TextView tv = view.findViewById(R.id.textViewAmount); tv.setText(getArguments().getString("amount"));
تمرير البيانات إلى وجهة البدء
يمكنك تمرير البيانات إلى وجهة بدء تطبيقك. أولاً، يجب عليك صراحةً
إنشاء Bundle
تحتفظ بالبيانات. بعد ذلك، استخدم أحد الأدوات التالية
الطُرق لتمرير Bundle
إلى وجهة البداية:
- في حال إنشاء
NavHost
آليًا، يمكنك الاتصالNavHostFragment.create(R.navigation.graph, args)
، حيثargs
Bundle
التي تحتفظ ببياناتك - بخلاف ذلك، يمكنك تعيين بدء وسيطات الوجهة من خلال استدعاء إحدى
الأحمال الزائدة التالية من
NavController.setGraph()
:- استخدِم معرّف الرسم البياني:
navController.setGraph(R.navigation.graph, args)
- استخدام الرسم البياني نفسه:
navController.setGraph(navGraph, args)
- استخدِم معرّف الرسم البياني:
لاسترداد البيانات في وجهة البدء، اتصل
Fragment.getArguments()
اعتبارات ProGuard
إذا كنت تعمل على تصغير الرمز، عليك منع Parcelable
،
Serializable
وEnum
أسماء الفئة من تشويشها كجزء من
ومزيد من البيانات. يمكنك القيام بذلك بإحدى الطريقتين:
- استخدِم التعليقات التوضيحية في Keep.
- استخدام قواعد Keepnames
توضّح الفقرات الفرعية التالية هذه المناهج.
استخدام التعليقات التوضيحية في Keep
يضيف المثال التالي تعليقات @Keep
التوضيحية إلى تعريفات فئات النماذج:
Kotlin
@Keep class ParcelableArg : Parcelable { ... } @Keep class SerializableArg : Serializable { ... } @Keep enum class EnumArg { ... }
Java
@Keep public class ParcelableArg implements Parcelable { ... } @Keep public class SerializableArg implements Serializable { ... } @Keep public enum EnumArg { ... }
استخدام قواعد Keepnames
يمكنك أيضًا إضافة keepnames
قاعدة إلى ملف proguard-rules.pro
، على النحو الموضّح.
في المثال التالي:
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
مصادر إضافية
للاطّلاع على مزيد من المعلومات حول التنقّل، يُرجى الرجوع إلى ما يلي: والموارد الإضافية.