แนวทางปฏิบัติแนะนำในการไปยังส่วนต่างๆ สำหรับโปรเจ็กต์หลายโมดูล

กราฟการนำทางอาจประกอบด้วยชุดค่าผสมของข้อมูลต่อไปนี้

  • ปลายทางเดียว เช่น ปลายทาง <fragment>
  • กราฟที่ซ้อนกัน ซึ่งรวมชุดปลายทางที่เกี่ยวข้องกัน
  • องค์ประกอบ <include> ซึ่งจะทำให้คุณสามารถฝังไฟล์กราฟการนำทางอื่น ซ้อนกันอยู่

ความยืดหยุ่นนี้ทำให้คุณสามารถรวมกราฟการนำทางขนาดเล็กเข้าด้วยกันเพื่อ สร้างกราฟการนำทางที่สมบูรณ์ของแอป แม้ว่าการนำทางที่เล็กกว่านั้น กราฟจะแสดงโดยโมดูลที่แยกจากกัน

สำหรับตัวอย่างในหัวข้อนี้ แต่ละรายการ โมดูลฟีเจอร์โฟกัสอยู่ ประมาณ ฟีเจอร์หนึ่ง และ มีกราฟการนำทางแบบเดียวที่สรุปจุดหมายปลายทางทั้งหมด ที่จำเป็นต่อการใช้ฟีเจอร์นั้น ในแอปเวอร์ชันที่ใช้งานจริง คุณอาจมี โมดูลย่อยในระดับที่ต่ำกว่าซึ่งเป็นรายละเอียดการใช้งานของระดับที่สูงกว่านี้ โมดูลฟีเจอร์ โมดูลฟีเจอร์เหล่านี้แต่ละโมดูลจะรวมอยู่ด้วย ไม่ว่าจะโดยตรงหรือ โดยอ้อมไปยัง app โมดูล ตัวอย่าง แอปพลิเคชันแบบหลายโมดูลที่ใช้ในเอกสารนี้ โครงสร้างต่อไปนี้

วันที่ กราฟทรัพยากร Dependency สำหรับตัวอย่างแอปพลิเคชันหลายโมดูล
ปลายทางเริ่มต้นของแอปตัวอย่าง
รูปที่ 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 ลงใน UI ของคุณ ภายในโมดูล 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 คลาสนี้มีเมธอดแบบคงที่ที่จัดการการนำทางด้วย แถบแอป ลิ้นชักการนำทาง และการนำทางด้านล่าง หากแอปของคุณ ปลายทางระดับบนสุดประกอบด้วยองค์ประกอบ UI ที่ได้จากฟีเจอร์ โมดูล app จึงเป็นพื้นที่ธรรมชาติในการวางหน่วยโฆษณาระดับบนสุด การนำทางและองค์ประกอบ UI เนื่องจากโมดูลแอปขึ้นอยู่กับ โมดูลฟีเจอร์การทำงานร่วมกัน และปลายทางทั้งหมดสามารถเข้าถึงได้ จากโค้ดที่กำหนดไว้ในโมดูลแอป ซึ่งหมายความว่าคุณสามารถใช้ 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 จัดการ Bottom Navigation, โทร 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 ก็จะไปยัง กราฟไลบรารีเมื่อผู้ใช้คลิกรายการการนำทางด้านล่าง

โปรดทราบว่าโดยปกติแล้วแนวทางปฏิบัติที่ไม่ดีที่โมดูลแอปจะต้อง การพึ่งพาโดยปลายทางที่เจาะจงซึ่งฝังตัวอยู่ลึกภายใน โมดูลฟีเจอร์ของคุณ กราฟการนำทาง ในกรณีส่วนใหญ่ คุณคงอยากให้แอปของคุณ โมดูลเพื่อให้ทราบเฉพาะจุดแรกเข้าไปยังจุดที่ฝังหรือ กราฟการนำทาง (ซึ่งใช้นอกโมดูลฟีเจอร์เช่นกัน) หากต้องการ เพื่อลิงก์ไปยังปลายทางลึกภายในกราฟการนำทางของห้องสมุด วิธีที่แนะนำคือการใช้ Deep Link การทำ Deep Link คือ และเป็นวิธีเดียวที่ไลบรารีจะนำทางไปยังปลายทางในอีก ของกราฟการนำทาง ของคลัง

การนำทางข้ามโมดูลฟีเจอร์

ขณะคอมไพล์ โมดูลฟีเจอร์อิสระจะไม่เห็นกันและกัน เพื่อไม่ให้ใช้รหัสเพื่อนำทางไปยังปลายทางในโมดูลอื่นๆ แต่ ใช้ Deep Link เพื่อไปยังส่วนต่างๆ ไปยังปลายทางที่เชื่อมโยงกับ implicit Deep Link

จากตัวอย่างก่อนหน้านี้ สมมติว่าคุณต้องไปยังส่วนต่างๆ จากปุ่มใน โมดูล :feature:home ไปยังปลายทางที่ฝังอยู่ใน :feature:settings โดยการเพิ่ม Deep Link ไปยังปลายทางในการตั้งค่า กราฟการนำทางดังที่แสดง

<?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 ระบบจะไม่รีเซ็ตสแต็กย้อนกลับ ลักษณะการทำงานนี้ ซึ่งต่างจากการไปยังส่วนต่างๆ ของ Deep Link อย่างชัดแจ้ง ซึ่งจะแทนที่สแต็กด้านหลังขณะนำทาง