OOZOU
تواصلوا معنا
العودة إلى المدونة

استخدام Deep Link في Android Navigation: طريقة سهلة لاستخدام Deep Link مع Navigation Component في المشاريع الكبيرة

أشرح في هذا المقال كيفية استخدام deep link مع Navigation Component في مشروع كبير، وأعرض بعض المشكلات التي قد تواجهونها أثناء التنفيذ.

24 ديسمبر 2020
8 دقائق للقراءة
استخدام Deep Link في Android Navigation: طريقة سهلة لاستخدام Deep Link مع Navigation Component في المشاريع الكبيرة

أصبح التنقل في Android أسهل من أي وقت مضى بفضل Jetpack Navigation Component. تتيح لكم هذه المكتبة بناء التنقل بين الشاشات دون عناء التعامل مع التدفقات المعقدة، ما يسهّل توسيع منظومة التنقل في المشاريع الكبيرة. مزايا Navigation Component1. تؤتمت عمليات fragment transactions، ما يجعل الكود أنظف. 2. تتولى إدارة back stack 2. تبسّط التعامل مع deep linking 3. تتيح Safe Args تمرير البيانات بين الشاشات بسهولة وبطريقة type-safe 4. تتولى حركات الانتقال (transition animations) 5. تسهّل التعامل مع Drawer وBottom Navigation 6. تجمع منطق التنقل في مكان واحد وتعرضه بصريًا

أشارككم في هذا المقال تجربتي وبعض المشكلات التي قد تواجهونها عند استخدام Jetpack Navigation Component في مشروع كبير. **لا تعيدوا استخدام الـ fragment نفسه في عدة navigation graphs.**في المشاريع الكبيرة لا مفر من إعادة استخدام fragment في أكثر من Navigation graph، لكن قد ينتهي بكم الأمر إلى هذا الخطأ:يظهر الخطأ عند محاولة إصدار المشروع مع pro-guards، لأن SafeArgs Plugin يولّد الفئتين Args.kt و Directions.kt لكل navigation graph، بينما لا تسمح pro-guards بوجود فئات مكررة.الحل: Nested Graph!عندما تحتاجون إلى استخدام fragment في عدة تدفقات، أنشئوا nested graph وأعيدوا استخدامه في أي مكان. الـ Deep-link هو البطل! لا يمكنكم التنبؤ بمتطلبات الأعمال المستقبلية، لكن يمكنكم الاستعداد للتغيير. ويستطيع deep-link في Navigation Component أن يجعل التدفق المعقد أبسط بكثير.

قد يبدأ المشروع بتدفق معقد للغاية، ثم تتغير المتطلبات يومًا ما فيحتاج التطبيق إلى جزء صغير فقط من ذلك التدفق الكبير. يمكننا بسهولة نسخ جزء من التدفق إلى تدفق جديد، لكننا سنقع في تكرار الكود. الحل هو تقسيم التدفق إلى أجزاء أصغر باستخدام nested graph كما ذكرت سابقًا، واستخدام deep link للتنقل. Global Action **الـ Global action طريقة أخرى للوصول إلى navigation graphs من أي مكان، حتى من داخل nested graph، تمامًا مثل deep link، لكن لا يمكن الوصول إليها من تطبيق آخر.إنشاء deep linksلنأخذ مشروع سلة تسوق يضم قائمة منتجات وسلة تسوق ودفعًا وسجلًا للطلبات وغير ذلك. المشروع أيضًا مقسّم إلى وحدات حسب الميزة ويعتمد Single Activity Architecture. أفترض أنكم تعرفون مسبقًا كيفية إعداد navigation graphs أساسية وإنشائها. وإن لم تكونوا كذلك، يمكنكم التعلّم عبر code lab من Google. عند إنشاء navigation graph، أنصح بإنشاء deep link واحد لكل تدفق بحيث يمكن الوصول إلى التدفق من أي مكان في المشروع. ثم استخدموا deep link للتنقل بين صفحات التطبيق، فقد تحتاجون إلى deep links في المستقبل. إنشاء Listing graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_listing"
    app:startDestination="@id/listingFragment">

    <fragment
        android:id="@+id/listingFragment"
        android:name="com.him.oozoublog.navcom.listing.ui.listing.ListingFragment"
        android:label="fragment_listing"
        tools:layout="@layout/fragment_listing">
        <deepLink
            android:id="@+id/deepLink"
            app:uri="myapp://listing" />
    </fragment>
    ......
</navigation>
<em>language-</em>xml

إنشاء navigation graph لسلة التسوق

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_shopping_cart"
    app:startDestination="@id/shoppingCartFragment">

    <fragment
        android:id="@+id/shoppingCartFragment"
        android:name="com.him.oozoublog.navcom.shoppingcart.ui.ShoppingCartFragment"
        android:label="ShoppingCartFragment">
        <deepLink
            android:id="@+id/deepLink"
            app:uri="myapp://shopping-cart" />
    </fragment>
</navigation>
<em>language-</em>xml

إنشاء navigation graph للسجل

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/history_navigation"
    app:startDestination="@id/historyFragment">

    <fragment
        android:id="@+id/historyFragment"
        android:name="com.him.oozoublog.navcom.history.ui.HistoryFragment"
        android:label="HistoryFragment">
        <deepLink
            android:id="@+id/deepLink"
            app:uri="myapp://history" />
    </fragment>
</navigation>
<em>language-</em>xml

إنشاء navigation graph للدفع

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_payment"
    app:startDestination="@id/paymentFragment">

    <fragment
        android:id="@+id/paymentFragment"
        android:name="com.him.oozoublog.navcom.payment.ui.PaymentFragment"
        android:label="PaymentFragment">
        <deepLink
            android:id="@+id/deepLink"
            app:uri="myapp://payment" />
    </fragment>
</navigation>
<em>language-</em>xml

إنشاء main navigation graphلا يحتوي main navigation graph فعليًا على أي شيء سوى تضمين جميع الـ graphs التي يجب دمجها في المشروع.

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_navigation"
    app:startDestination="@+id/navigation_listing">

    <include app:graph="@navigation/navigation_listing" />

    <include app:graph="@navigation/navigation_history" />

    <include app:graph="@navigation/navigation_shopping_cart" />

    <include app:graph="@navigation/navigation_payment" />

</navigation>
<em>language-</em>xml

معالج Deep-link نحتاج إلى فئة تضم جميع deep links المدعومة ويمكن الوصول إليها من أي مكان في المشروع. ويمكننا أيضًا إضافة دوال مخصصة حسب الحاجة.

object InternalDeepLink {
    const val DOMAIN = "myapp://"

    const val LISTING = "${DOMAIN}listing"
    const val PAYMENT = "${DOMAIN}payment"
    const val SHOPPING_CART = "${DOMAIN}shopping-cart"
    const val HISTORY = "${DOMAIN}history"

    fun makeCustomDeepLink(id: String): String {
        return "${DOMAIN}customDeepLink?id=${id}"
    }
}

كيفية استخدام deep links استخدام deep links سهل جدًا. يمكنكم التنقل إلى جميع الشاشات التي تدعم deep links على النحو التالي:

listingViewModel._navigateToShoppingCart.observe(<em>viewLifecycleOwner</em>, <strong>{
    </strong>val deepLink = InternalDeepLink.SHOPPING_CART.<em>toUri</em>()
    <em>findNavController</em>().navigate(deepLink)
<strong>}</strong>)

يمكننا استخدام enums في deep links **تتيح مكتبة Navigation تمرير فئة enum مخصصة بين الوجهات، ويمكنكم الاطلاع على أنواع الوسائط المدعومة.على سبيل المثال، يمكن لصفحة القائمة البحث عن السيارات أو الساعات أو كليهما.

enum class SearchType {
    ALL,
    CAR,
    WATCH
}

أضيفوا وسيطًا (argument) إلى listing graph

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_listing"
    app:startDestination="@id/listingFragment">

    <fragment
        android:id="@+id/listingFragment"
        android:name="com.him.oozoublog.navcom.listing.ui.listing.ListingFragment"
        android:label="fragment_listing"
        tools:layout="@layout/fragment_listing">
        <argument
            android:name="searchType"
            android:defaultValue="ALL"
            app:argType="com.him.oozoublog.navcom.listing.ui.listing.SearchType" />
        <deepLink
            android:id="@+id/deepLink"
            app:uri="myapp://listing?searchType={searchType}" />
    </fragment>
</navigation>
<em>language-</em>xml

**كيفية الحصول على البيانات من deep links.**عندما ننتقل إلى صفحة أخرى مع بعض البيانات، يتولى SafeArgs Plugin معالجة هذه البيانات تلقائيًا. وعند إعادة بناء المشروع ستجدون الملف ListingFragmentArgs.kt. كما يحوّل هذا الـ plugin البيانات إلى فئتكم المخصصة إن وُجدت. يمكنكم استخدام navArgs() delegate لتمرير البيانات على النحو التالي:

class ListingFragment : Fragment() { 
    ....
    private val args: ListingFragmentArgs by <em>navArgs</em>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i("search type", args.searchType.name)
    }
    ....
}

مقدمة إلى Deep Links

تُعد deep links أداة قوية في تطوير Android، ويمكنها تحسين تجربة المستخدم داخل التطبيق بشكل ملحوظ. فهي في جوهرها روابط URL فريدة توجّه المستخدم إلى موضع محدد داخل التطبيق دون الحاجة إلى المرور بعدة شاشات. وعند استخدامها مع Navigation Component، تبسّط deep links التنقل داخل التطبيق وتجعله أوضح وأكثر كفاءة للمستخدمين. وبتطبيقها تضمنون وصول المستخدمين إلى المحتوى الذي يحتاجونه بسرعة، ما يرفع مستوى التفاعل والرضا عمومًا.

إعداد Navigation Component

لإعداد Navigation Component في مشروعكم، تحتاجون إلى إضافة اعتماديات المكتبة اللازمة. افتحوا ملف build.gradle وأضيفوا التبعيات التالية:

dependencies { implementation 'androidx.navigation:navigation-fragment:2.3.5' implementation 'androidx.navigation:navigation-ui:2.3.5' }

بعد ذلك، أنشئوا navigation graph، وهو ملف موارد مركزي يضم جميع المعلومات المتعلقة بالتنقل. لإنشائه، أضيفوا ملف موارد جديدًا إلى المشروع وعرّفوا فيه الوجهات (destinations) والإجراءات (actions). يساعدكم هذا الـ graph على إدارة تدفق التنقل في التطبيق ورؤيته بصريًا، ما يسهّل تنفيذه وصيانته.

إنشاء Deep Link ومعالجته

لإنشاء deep link تضيفون عنصر deep link إلى navigation graph. يحدد هذا العنصر الوجهة التي ينبغي أن ينقل إليها الرابط. ولإضافته، انقروا على الوجهة المطلوبة في navigation graph واختاروا “Add deep link” من القائمة السياقية. ثم عرّفوا الـ URI الخاص بالرابط وتأكدوا من أنه يشير إلى الوجهة الصحيحة.

أما معالجة deep link فتتطلب إعادة تعريف (override) الدالة onNewIntent في الـ activity. واستدعوا داخلها handleDeepLink من Navigation Component للانتقال إلى الوجهة المحددة:

@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Navigation.findNavController(this, R.id.nav_host_fragment).handleDeepLink(intent); }

باتباع هذه الخطوات يمكنكم إنشاء deep links ومعالجتها بفعالية، وضمان تنقل سلس داخل التطبيق.

أفضل الممارسات مع Navigation Component

عند استخدام Navigation Component، راعوا الممارسات التالية لتحسين التنفيذ:

  • استخدموا Navigation Graph واحدًا: احتفظوا بـ navigation graph واحد للتطبيق بأكمله لجمع منطق التنقل في مكان واحد وتبسيط إدارته.
  • فضّلوا Fragments على Activities: استخدموا fragments كوجهات بدلًا من activities للاستفادة من مزايا Navigation Component.
  • استخدموا NavController: تنقلوا بين الوجهات عبر NavController لضمان سلوك تنقل متسق ومتوقع.
  • استفيدوا من NavigationUI: استخدموا NavigationUI للتعامل مع عناصر الواجهة المرتبطة بالتنقل، مثل navigation drawer وbottom navigation.
  • اختبروا Navigation Graph جيدًا: اختبروا navigation graph بانتظام للتأكد من أنه يعمل كما هو متوقع ويقدم تجربة مستخدم سلسة.

بالالتزام بهذه الممارسات يمكنكم الاستفادة القصوى من Navigation Component وبناء نظام تنقل متين لتطبيقكم.

اختبار Deep Links وتشخيص مشكلاتها

اختبار deep links ضروري للتأكد من أنها تعمل بشكل صحيح. يمكنكم استخدام أداة adb لمحاكاة رابط deep link. على سبيل المثال، لاختبار deep link شغّلوا الأمر التالي: adb shell am start -n com.example.myapp/.MainActivity -d "http://example.com/deeplink" ولتشخيص المشكلات، استخدموا أداة Logcat لعرض السجلات المتعلقة بالتنقل، فهي تساعدكم على تحديد أي مشكلة وحلها. كما تتيح أداة debug الخاصة بـ Navigation Component عرض navigation graph بصريًا، ما يسهّل اكتشاف المشكلات وإصلاحها.

باتباع أساليب الاختبار والتشخيص هذه تضمنون أن تعمل deep links بشكل صحيح وتقدم تجربة مستخدم سلسة.هذا كل شيء. بهذه السهولة يمكنكم استخدام deep links في Navigation Component لمعالجة الروابط داخل تطبيقكم. شاركونا أي أفكار أخرى لديكم، ويمكنكم العثور على الكود المصدري على Github. المراجع: **- https://developer.android.com/guide/navigation- https://proandroiddev.com/scalable-architecture-for-big-mobile-projects-c48f329a2275- https://medium.com/@yuri.live/scalability-and-maintainability-of-mobile-and-other-applications-part-1-21e3d07dadeb- https://medium.com/@piyushgupta77/android-app-architecture-portable-scalable-reusable-2527af3d870a- https://www.youtube.com/watch?v=Y0Cs2MQxyIs- https://proandroiddev.com/android-navigation-component-fc783c03bb8d

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد