---
title: "استخدام Deep Link في Android Navigation: طريقة سهلة لاستخدام Deep Link مع Navigation Component في المشاريع الكبيرة"
description: "كيفية استخدام deep link مع Navigation Component في مشروع Android كبير، مع أبرز المشكلات التي قد تواجهونها أثناء التنفيذ وطرق حلها."
canonical: https://oozou.com/ar/blog/using-android-navigation-deeplink-an-easy-way-to-use-deep-link-in-navigation-component-on-a-big-project-97
locale: ar
date: 2020-12-24
author: "OOZOU Team"
---

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

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

Published: 2020-12-24 · Author: OOZOU Team (Engineering) · 8 min read

أصبح التنقل في Android أسهل من أي وقت مضى بفضل [Jetpack Navigation Component](https://developer.android.com/guide/navigation). تتيح لكم هذه المكتبة بناء التنقل بين الشاشات دون عناء التعامل مع التدفقات المعقدة، ما يسهّل توسيع منظومة التنقل في المشاريع الكبيرة.
**مزايا Navigation Component**1\. تؤتمت عمليات fragment transactions، ما يجعل الكود أنظف.
2. تتولى إدارة back stack
2. تبسّط التعامل مع deep linking
3. تتيح [Safe Args](https://developer.android.com/guide/navigation/navigation-pass-data#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](https://developer.android.com/guide/navigation/navigation-getting-started#ensure_type-safety_by_using_safe_args) يولّد الفئتين **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**لنأخذ مشروع سلة تسوق يضم قائمة منتجات وسلة تسوق ودفعًا وسجلًا للطلبات وغير ذلك. المشروع أيضًا [مقسّم إلى وحدات حسب الميزة](https://medium.com/swlh/modularization-by-feature-and-layer-with-android-architecture-components-80bf317d737) ويعتمد [Single Activity Architecture.](https://www.youtube.com/watch?v=2k8x8V77CrU) أفترض أنكم تعرفون مسبقًا كيفية إعداد navigation graphs أساسية وإنشائها. وإن لم تكونوا كذلك، يمكنكم التعلّم عبر [code lab من Google](https://codelabs.developers.google.com/codelabs/android-navigation).
عند إنشاء 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 المدعومة ويمكن الوصول إليها من أي مكان في المشروع. ويمكننا أيضًا إضافة دوال مخصصة حسب الحاجة.

```kotlin
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 على النحو التالي:

```kotlin
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 مخصصة بين الوجهات، ويمكنكم الاطلاع على [أنواع الوسائط المدعومة](https://developer.android.com/guide/navigation/navigation-pass-data).على سبيل المثال، يمكن لصفحة القائمة البحث عن السيارات أو الساعات أو كليهما.

```kotlin
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](https://developer.android.com/guide/navigation/navigation-getting-started#ensure_type-safety_by_using_safe_args) معالجة هذه البيانات تلقائيًا. وعند إعادة بناء المشروع ستجدون الملف **ListingFragmentArgs.kt.** كما يحوّل هذا الـ plugin البيانات إلى فئتكم المخصصة إن وُجدت.
يمكنكم استخدام navArgs() delegate لتمرير البيانات على النحو التالي:

```kotlin
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 وأضيفوا التبعيات التالية:

```kotlin
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 للانتقال إلى الوجهة المحددة:

```kotlin
@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://github.com/arohim/oozoublog-navcom).
المراجع:
**[**\- https://developer.android.com/guide/navigation**](https://developer.android.com/guide/navigation)[**\- https://proandroiddev.com/scalable-architecture-for-big-mobile-projects-c48f329a2275**](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/@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://medium.com/@piyushgupta77/android-app-architecture-portable-scalable-reusable-2527af3d870a)[**\- https://www.youtube.com/watch?v=Y0Cs2MQxyIs**](https://www.youtube.com/watch?v=Y0Cs2MQxyIs)[**\- https://proandroiddev.com/android-navigation-component-fc783c03bb8d**](https://proandroiddev.com/android-navigation-component-fc783c03bb8d)

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/ar/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
