روال‌های مطلوب پیمایش برای پروژه‌های چندماژولی

نمودار ناوبری می‌تواند شامل هر ترکیبی از موارد زیر باشد:

  • یک مقصد واحد، مثل مقصد <fragment>.
  • نمودار تودرتو که مجموعه‌ای از مقصدهای مرتبط را دربرمی‌گیرد.
  • عنصر <include>، که به شما امکان می‌دهد فایل نمودار ناوبری دیگری را جاسازی کنید، گویی که تودرتو است.

این انعطاف‌پذیری به شما امکان می‌دهد نمودارهای ناوبری کوچک‌تر را باهم ترکیب کنید تا نمودار ناوبری کامل برنامه‌تان را تشکیل دهید، حتی اگر آن نمودارهای ناوبری کوچک‌تر توسط مدول‌های جداگانه ارائه شده باشند.

ارائه می‌دهد.

برای مثال‌های این موضوع، هر واحد ویژگی بر یک ویژگی متمرکز است و یک نمودار پیمایش واحد ارائه می‌دهد که همه مقصدهای موردنیاز برای پیاده‌سازی آن ویژگی را دربرمی‌گیرد. در برنامه تولید، ممکن است زیرواحدهای زیادی در سطح پایین‌تر داشته باشید که جزئیات پیاده‌سازی این واحد ویژگی سطح بالاتر هستند. هرکدام از این واحدهای ویژگی، به‌طور مستقیم یا غیرمستقیم، در app واحد شما گنجانده شده‌اند. نمونه برنامه چندماژولی استفاده‌شده در این سند ساختار زیر را دارد:

نمودار وابستگی برای نمونه برنامه چندماژولی
مقصد شروع برنامه نمونه
شکل ۱. معماری برنامه و مقصد شروع برای برنامه نمونه.

هر واحد ویژگی یک واحد مستقل با نمودار پیمایش و مقصدهای خاص خود است. ماژول app به هرکدام وابسته است و آن‌ها را به‌عنوان جزئیات پیاده‌سازی در فایل build.gradle خود اضافه می‌کند، همان‌طور که نشان داده شده است:

شیک

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

کاتلین

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 برای مرتبط کردن مقصدها به گزینه‌های منو استفاده کنید، اگر شناسه گزینه با شناسه مقصد مطابقت داشته باشد.

در شکل ۲، نمونه ماژول 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() در کلاس فعالیت اصلی‌تان فراخوانی کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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 دکمه در قطعه صفحه اصلی اضافه کنید:

کاتلین

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

جاوا

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، پشته قبلی‌ها بازنشانی نمی‌شود. این رفتار برخلاف پیمایش پیوند عمیق صریح است که در آن پشته قبلی‌ها هنگام پیمایش جایگزین می‌شود.