Phân chia mã điều hướng thành các phần

Trang này hướng dẫn cách mô-đun hoá mã điều hướng. Tài liệu này nhằm bổ sung cho hướng dẫn chung về mô-đun hoá ứng dụng.

Tổng quan

Mô-đun hoá mã điều hướng là quá trình tách các khoá điều hướng có liên quan và nội dung mà các khoá đó đại diện thành các mô-đun riêng lẻ. Điều này giúp phân tách rõ ràng các trách nhiệm và cho phép bạn di chuyển giữa các tính năng khác nhau trong ứng dụng.

Để mô-đun hoá mã điều hướng, hãy làm như sau:

  • Tạo hai mô-đun con: api và impl cho mỗi tính năng trong ứng dụng
  • Đặt khoá điều hướng cho từng tính năng vào mô-đun api của tính năng đó
  • Đặt entryProviders và nội dung có thể điều hướng cho từng tính năng vào mô-đun impl liên quan
  • Cung cấp entryProviders cho các mô-đun ứng dụng chính, trực tiếp hoặc sử dụng tính năng chèn phần phụ thuộc

Tách các tính năng thành mô-đun con api và mô-đun con triển khai

Đối với mỗi tính năng trong ứng dụng, hãy tạo hai mô-đun con có tên là api và impl (viết tắt của "implementation" (triển khai)). Hãy sử dụng bảng sau để quyết định vị trí đặt mã điều hướng.

Tên mô-đun

Chứa

api

phím điều hướng

impl

Nội dung cho tính năng đó, bao gồm cả định nghĩa cho NavEntry và entryProvider. Hãy xem thêm phần phân giải khoá thành nội dung.

Phương pháp này cho phép một tính năng chuyển đến một tính năng khác bằng cách cho phép nội dung của tính năng đó (có trong mô-đun impl) phụ thuộc vào các khoá điều hướng của một mô-đun khác (có trong mô-đun api của mô-đun đó).

Sơ đồ phần phụ thuộc của mô-đun tính năng cho thấy cách các mô-đun `impl` có thể phụ thuộc vào các mô-đun `api`.
Hình 1. Biểu đồ phần phụ thuộc của mô-đun tính năng cho thấy cách các mô-đun triển khai có thể phụ thuộc vào mô-đun API.

Tách riêng các mục điều hướng bằng hàm mở rộng

Trong Navigation 3, nội dung có thể điều hướng được xác định bằng các mục điều hướng. Để tách các mục này thành các mô-đun riêng biệt, hãy tạo các hàm mở rộng trên EntryProviderScope rồi di chuyển các hàm đó vào mô-đun impl cho tính năng đó. Các trình tạo này được gọi là trình tạo mục nhập.

Ví dụ về mã sau đây cho thấy một trình tạo mục nhập tạo ra hai mục nhập điều hướng.

// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey

fun EntryProviderScope<NavKey>.featureAEntryBuilder() {
    entry<KeyA> {
        ContentRed("Screen A") {
            // Content for screen A
        }
    }
    entry<KeyA2> {
        ContentGreen("Screen A2") {
            // Content for screen A2
        }
    }
}

Gọi hàm đó bằng entryProvider DSL khi xác định entryProvider trong mô-đun ứng dụng chính.

// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
NavDisplay(
    entryProvider = entryProvider {
        featureAEntryBuilder()
    },
    // ...
)

Sử dụng tính năng chèn phần phụ thuộc để thêm các mục vào ứng dụng chính

Trong ví dụ về mã trước đó, mỗi trình tạo mục nhập được ứng dụng chính gọi trực tiếp bằng DSL entryProvider. Nếu ứng dụng của bạn có nhiều màn hình hoặc mô-đun tính năng, thì mẫu này có thể không mở rộng được.

Để giải quyết vấn đề này, hãy để mỗi mô-đun tính năng đóng góp trình tạo mục nhập vào hoạt động của ứng dụng bằng cách chèn phần phụ thuộc.

Ví dụ: mã sau đây sử dụng Dagger multibindings, cụ thể là @IntoSet, để chèn trình tạo mục nhập vào Set do MainActivity sở hữu. Sau đó, các hàm này được gọi lặp lại bên trong entryProvider, loại bỏ nhu cầu gọi rõ ràng nhiều hàm của trình tạo mục nhập.

Mô-đun tính năng

// import dagger.Module
// import dagger.Provides
// import dagger.hilt.InstallIn
// import dagger.hilt.android.components.ActivityRetainedComponent
// import dagger.multibindings.IntoSet

@Module
@InstallIn(ActivityRetainedComponent::class)
object FeatureAModule {

    @IntoSet
    @Provides
    fun provideFeatureAEntryBuilder() : EntryProviderScope<NavKey>.() -> Unit = {
        featureAEntryBuilder()
    }
}

Mô-đun ứng dụng

// import android.os.Bundle
// import androidx.activity.ComponentActivity
// import androidx.activity.compose.setContent
// import androidx.navigation3.runtime.EntryProviderScope
// import androidx.navigation3.runtime.NavKey
// import androidx.navigation3.runtime.entryProvider
// import androidx.navigation3.ui.NavDisplay
// import javax.inject.Inject

class MainActivity : ComponentActivity() {

    @Inject
    lateinit var entryBuilders: Set<@JvmSuppressWildcards EntryProviderScope<NavKey>.() -> Unit>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NavDisplay(
                entryProvider = entryProvider {
                    entryBuilders.forEach { builder -> this.builder() }
                },
                // ...
            )
        }
    }
}

Nếu các mục điều hướng cần điều hướng (ví dụ: các mục này chứa các phần tử trên giao diện người dùng điều hướng đến màn hình mới), hãy chèn một đối tượng có khả năng sửa đổi state điều hướng của ứng dụng vào từng hàm của trình tạo.

Nếu ứng dụng của bạn hỗ trợ đường liên kết sâu và được mô-đun hoá, thì mỗi mô-đun tính năng phải xác định các thực thể DeepLinkMatcher cho đích đến mà mô-đun đó sở hữu.

Để đối chiếu tất cả trình so khớp trong ứng dụng, bạn có thể sử dụng tính năng liên kết nhiều phần tử chèn phần phụ thuộc. Ví dụ: mỗi mô-đun tính năng có thể đóng góp trình so khớp của mình vào một liên kết đa chiều @IntoSet của Dagger:

Mô-đun tính năng

Sau đó, trong mô-đun ứng dụng chính, chẳng hạn như trong MainActivity, bạn có thể chèn tập hợp trình so khớp và sử dụng chúng để so khớp các yêu cầu đến:

Mô-đun ứng dụng

Để biết thêm thông tin về cách xác định và xử lý đường liên kết sâu, hãy xem phần Hỗ trợ đường liên kết sâu.

Tài nguyên

Để xem các mã mẫu minh hoạ cách mô-đun hoá mã Navigation 3, hãy xem: