שיטות מומלצות לניווט בפרויקטים עם מודולים מרובים

תרשים ניווט יכול להכיל כל שילוב של:

  • יעד יחיד, למשל יעד <fragment>.
  • תרשים בתוך תרשים שכולל קבוצה של יעדים קשורים.
  • רכיב <include>, שמאפשר להטמיע קובץ אחר של תרשים ניווט כאילו היה בתצוגת עץ.

הגמישות הזו מאפשרת לשלב תרשימי ניווט קטנים יותר יוצרת את תרשים הניווט המלא של האפליקציה, גם אם הניווטים קטנים יותר והתרשימים מסופקים על ידי מודולים נפרדים.

הדוגמאות בנושא הזה, כל אחת במודול של התכונות ממוקד לגבי תכונה אחת מספקת תרשים ניווט אחד שמכסה את כל היעדים שנדרש כדי ליישם את התכונה הזו. באפליקציה בסביבת ייצור, מודולים משניים ברמה נמוכה יותר שהם פרטי ההטמעה של הרמה הגבוהה יותר של התכונה. כל אחד מהמודולים של התכונות האלה כלול, באופן ישיר או בעקיפין דרך מודול app. הדוגמה של multi-Module application שנעשה בו שימוש במסמך זה יש את במבנה הבא:

תרשים תלות של אפליקציה עם מודולים מרובים לדוגמה
יעד ההתחלה של האפליקציה לדוגמה
איור 1. ארכיטקטורת האפליקציות והיעד ההתחלתי את האפליקציה לדוגמה.

כל מודול של תכונה הוא יחידה עצמאית עם גרף ניווט משלו. ויעדים. המודול app תלוי בכל אחד מהם, מוסיף אותם בתור פרטי ההטמעה בקובץ build.gradle, כפי שמוצג:

מגניב

dependencies {
    ...
    implementation project(":feature:home")
    implementation project(":feature:favorites")
    implementation project(":feature:settings")

Kotlin

dependencies {
    ...
    implementation(project(":feature:home"))
    implementation(project(":feature:favorites"))
    implementation(project(":feature:settings"))

התפקיד של המודול app

המודול app אחראי לספק את התרשים המלא של ולהוסיף את NavHost לממשק המשתמש. במודול app אפשר להפנות לתרשימים של הספרייה באמצעות <include>. בזמן השימוש בפונקציה <include> זהה מבחינה פונקציונלית לשימוש בתרשים מקונן, ב-<include> יש תמיכה בתרשימים ממודולים אחרים של פרויקטים או מהספרייה כמו בדוגמה הבאה:

<?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/nav_graph"
    app:startDestination="@id/home_nav_graph">

    <include app:graph="@navigation/home_navigation" />
    <include app:graph="@navigation/favorites_navigation" />
    <include app:graph="@navigation/settings_navigation" />
</navigation>

אחרי שספרייה נכללת בתרשים הניווט ברמה העליונה, ניתן: ניווט לתרשימים של הספרייה לפי הצורך. לדוגמה, אפשר ליצור פעולה כדי לנווט לתרשים ההגדרות מתוך מקטע בתרשים הניווט, כפי שמוצג:

<?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/nav_graph"
    app:startDestination="@id/home_nav_graph">

    <include app:graph="@navigation/home_navigation" />
    <include app:graph="@navigation/favorites_navigation" />
    <include app:graph="@navigation/settings_navigation" />

    <fragment
        android:id="@+id/random_fragment"
        android:name="com.example.android.RandomFragment"
        android:label="@string/fragment_random" >
        <!-- Launch into Settings Navigation Graph -->
        <action
            android:id="@+id/action_random_fragment_to_settings_nav_graph"
            app:destination="@id/settings_nav_graph" />
    </fragment>
</navigation>

כשכמה מודולים של תכונות צריכים להפנות לקבוצה משותפת של יעדים, כמו תרשים התחברות, אסור לכלול אותם יעדים נפוצים בתרשים הניווט של כל מודול של תכונה. במקום זאת, להוסיף את היעדים הנפוצים האלה לתרשים הניווט של מודול app. לאחר מכן, כל מודול של מאפיין יכול לנווט בין מודולים של תכונות כדי לנווט ליעדים הנפוצים האלה.

בדוגמה הקודמת, הפעולה מציינת יעד לניווט מתוך @id/settings_nav_graph. המזהה הזה מתייחס ליעד מוגדר בתרשים הכלול @navigation/settings_navigation.

ניווט ברמה העליונה במודול האפליקציה

רכיב הניווט כולל NavigationUI. הכיתה הזו מכילה שיטות סטטיות שמנהלות את הניווט באמצעות החלק העליון של המסך את סרגל האפליקציות, את חלונית ההזזה לניווט ואת הניווט התחתון. אם יעדים ברמה העליונה מורכבים מרכיבי ממשק המשתמש שמסופקים על ידי התכונה המודול app הוא מקום טבעי שבו ניתן להציב את רכיבי ניווט וממשק משתמש. מאחר שמודול האפליקציה תלוי משתפים מודולים של פיצ'רים, וכל היעדים שלהם נגישים מקוד שהוגדר במודול האפליקציה. כלומר, אתם יכולים להשתמש NavigationUI עד קישור בין היעדים לאפשרויות בתפריט אם המזהה של הפריט תואם למזהה של היעד.

באיור 2, המודול app לדוגמה מגדיר BottomNavigationView בפעילות העיקרית שלו. מזהי האפשרויות בתפריט תואמים לפרטים בניווט מזהי התרשימים של התרשימים בספרייה:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@id/home_nav_graph"
        android:icon="@drawable/ic_home"
        android:title="Home"
        app:showAsAction="ifRoom"/>

    <item
        android:id="@id/favorites_nav_graph"
        android:icon="@drawable/ic_favorite"
        android:title="Favorites"
        app:showAsAction="ifRoom"/>

    <item
        android:id="@id/settings_nav_graph"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="ifRoom" />
</menu>

כדי לאפשר ל-NavigationUI לטפל ב- ניווט תחתון, שיחה setupWithNavController() מ-onCreate() בכיתת הפעילות הראשית, כפי שמוצג בהמשך דוגמה:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController

    findViewById<BottomNavigationView>(R.id.bottom_nav)
            .setupWithNavController(navController)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    NavHostFragment navHostFragment =
            (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);

    NavigationUI.setupWithNavController(bottomNav, navController);
}

אחרי שהקוד הזה מותקן, NavigationUI מנווט אל תרשים ספרייה כשמשתמש לוחץ על פריט ניווט תחתון.

חשוב לזכור שבדרך כלל לא מומלץ להפעיל את מודול האפליקציה תלות חמורה ביעד ספציפי שמוטמע עמוק את המודולים של התכונות תרשים ניווט. ברוב המקרים, רצוי להשתמש באפליקציה לדעת רק על נקודת הכניסה לכל פריט מוטמע או כלול תרשימי ניווט (רלוונטי גם למודולים של תכונות). אם צריך כדי לקשר ליעד שנמצא עמוק בתרשים הניווט של הספרייה, שעדיף לעשות זאת קישור עומק. קישורי העומק הם זו גם הדרך היחידה שבה ספרייה יכולה לנווט ליעד אחר בתרשים הניווט של הספרייה.

ניווט בין מודולים של תכונות

בזמן הידור, מודולים בלתי תלויים של תכונות לא יכולים לראות זה את זה לכן לא תוכלו להשתמש במזהים כדי לנווט ליעדים במודולים אחרים. במקום זאת, להשתמש בקישור עומק כדי לנווט ישירות ליעד שמשויך אל קישור עומק מרומז.

בהמשך לדוגמה הקודמת, נניח שצריך לנווט מלחצן את המודול :feature:home ליעד שמוצב ברכיב :feature:settings של מודל טרנספורמר. אפשר לעשות זאת על ידי הוספת קישור עומק ליעד בהגדרות בתרשים הניווט, כפי שמוצג:

<?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/settings_nav_graph"
    app:startDestination="@id/settings_fragment_one">

    ...

    <fragment
        android:id="@+id/settings_fragment_two"
        android:name="com.example.google.login.SettingsFragmentTwo"
        android:label="@string/settings_fragment_two" >

        <deepLink
            app:uri="android-app://example.google.app/settings_fragment_two" />
    </fragment>
</navigation>

אחר כך צריך להוסיף את הקוד הבא אל onClickListener של הלחצן בבית מקטע:

Kotlin

button.setOnClickListener {
    val request = NavDeepLinkRequest.Builder
        .fromUri("android-app://example.google.app/settings_fragment_two".toUri())
        .build()
    findNavController().navigate(request)
}

Java

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        NavDeepLinkRequest request = NavDeepLinkRequest.Builder
            .fromUri(Uri.parse("android-app://example.google.app/settings_fragment_two"))
            .build();
        NavHostFragment.findNavController(this).navigate(request);
    }
});

בניגוד לניווט באמצעות מזהי פעולה או מזהי יעדים, אפשר לנווט אל כל URI בכל תרשים, אפילו בכל המודולים.

בניווט באמצעות URI, המקבץ האחורי לא מתאפס. מה קורה? בניגוד לניווט מפורש בקישורי עומק, המקבץ האחורי מוחלפת במהלך הניווט.