Di chuyển Jetpack Navigation sang Navigation Compose

API Điều hướng Compose cho phép bạn điều hướng giữa các thành phần kết hợp trong ứng dụng Compose, đồng thời tận dụng thành phần, cơ sở hạ tầng và các tính năng của Điều hướng Jetpack.

Trang này mô tả cách di chuyển từ thành phần Điều hướng Jetpack dựa trên mảnh sang Điều hướng trong Compose, trong quá trình di chuyển giao diện người dùng lớn hơn dựa trên Thành phần hiển thị sang Jetpack Compose.

Điều kiện tiên quyết để di chuyển

Bạn có thể chuyển sang Navigation Compose (Thành phần điều hướng Compose) sau khi có thể thay thế tất cả các Mảnh bằng các thành phần kết hợp màn hình tương ứng. Các thành phần kết hợp màn hình có thể chứa kết hợp nội dung Compose và Khung hiển thị, nhưng tất cả đích đến điều hướng phải là thành phần kết hợp để cho phép di chuyển Navigation Compose. Cho đến lúc đó, bạn nên tiếp tục sử dụng Thành phần điều hướng dựa trên mảnh trong cơ sở mã Khung hiển thị và Compose có khả năng tương tác. Hãy xem tài liệu về khả năng tương tác điều hướng để biết thêm thông tin.

Việc sử dụng Navigation Compose trong ứng dụng chỉ dành cho Compose không phải là điều kiện tiên quyết. Bạn có thể tiếp tục sử dụng Thành phần điều hướng dựa trên mảnh, miễn là bạn giữ lại Mảnh để lưu trữ nội dung thành phần kết hợp.

Các bước di chuyển

Cho dù đang làm theo chiến lược di chuyển đề xuất hay thực hiện một phương pháp khác, bạn đều sẽ đạt đến một điểm mà tất cả các đích điều hướng đều là thành phần kết hợp màn hình, trong đó Mảnh chỉ đóng vai trò là vùng chứa thành phần kết hợp. Ở giai đoạn này, bạn có thể chuyển sang Navigation Compose.

Nếu ứng dụng của bạn đã tuân theo mẫu thiết kế UDFhướng dẫn về cấu trúc của chúng tôi, thì việc di chuyển sang Jetpack Compose và Navigation Compose không yêu cầu tái cấu trúc chính các lớp khác của ứng dụng, ngoài lớp giao diện người dùng.

Để di chuyển sang Navigation Compose, hãy làm theo các bước sau:

  1. Thêm phần phụ thuộc Navigation Compose vào ứng dụng.
  2. Tạo một thành phần kết hợp App-level rồi thêm thành phần đó vào Activity làm điểm truy cập Compose, thay thế phần thiết lập của bố cục Thành phần hiển thị:

    class SampleActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample)
            setContent {
                SampleApp(/* ... */)
            }
        }
    }

  3. Thiết lập NavController ở một nơi mà tất cả các thành phần kết hợp cần tham chiếu đến lớp này đều có quyền truy cập vào lớp này (thường nằm bên trong thành phần kết hợp App). Phương pháp này tuân theo các nguyên tắc chuyển trạng thái lên trên và cho phép bạn sử dụng NavController làm nguồn đáng tin cậy để điều hướng giữa các màn hình có thể kết hợp và duy trì ngăn xếp lui:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
        // ...
    }

  4. Tạo NavHost của ứng dụng bên trong thành phần kết hợp Ứng dụng và truyền navController:

    @Composable
    fun SampleApp() {
        val navController = rememberNavController()
    
        SampleNavHost(navController = navController)
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            // ...
        }
    }

  5. Thêm các đích đến composable để tạo biểu đồ điều hướng. Nếu trước đó mỗi màn hình đã được di chuyển sang Compose, thì bước này chỉ bao gồm việc trích xuất các thành phần kết hợp màn hình này từ Mảnh vào đích đến composable:

    class FirstFragment : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            return ComposeView(requireContext()).apply {
                setContent {
                    // FirstScreen(...) EXTRACT FROM HERE
                }
            }
        }
    }
    
    @Composable
    fun SampleNavHost(
        navController: NavHostController
    ) {
        NavHost(navController = navController, startDestination = "first") {
            composable("first") {
                FirstScreen(/* ... */) // EXTRACT TO HERE
            }
            composable("second") {
                SecondScreen(/* ... */)
            }
            // ...
        }
    }

  6. Nếu bạn làm theo hướng dẫn về cấu trúc giao diện người dùng Compose, cụ thể là cách truyền ViewModel và sự kiện điều hướng đến các thành phần kết hợp, bước tiếp theo là thay đổi cách bạn cung cấp ViewModel cho từng thành phần kết hợp màn hình. Thường thì bạn có thể sử dụng tính năng chèn Hilt và điểm tích hợp với tính năng Compose và Điều hướng thông qua hiltViewModel:

    @Composable
    fun FirstScreen(
        // viewModel: FirstViewModel = viewModel(),
        viewModel: FirstViewModel = hiltViewModel(),
        onButtonClick: () -> Unit = {},
    ) {
        // ...
    }

  7. Thay thế tất cả lệnh gọi điều hướng findNavController() bằng các lệnh gọi navController và truyền các lệnh này dưới dạng sự kiện điều hướng đến từng màn hình có thể kết hợp, thay vì truyền toàn bộ navController. Phương pháp này tuân theo các phương pháp hay nhất để hiển thị sự kiện từ các hàm có khả năng kết hợp cho phương thức gọi và giữ navController làm nguồn đáng tin cậy duy nhất.

    1. Nếu trước đây bạn đã sử dụng trình bổ trợ Safe Args để tạo đường đi và thao tác điều hướng, hãy thay thế bằng một tuyến đường – một đường dẫn Chuỗi đến thành phần kết hợp là duy nhất cho mỗi đích đến.
    2. Để thay thế Safe Args khi truyền dữ liệu, hãy xem phần Điều hướng bằng đối số.
    3. Để đảm bảo an toàn về kiểu trong Navigation Compose, vui lòng đọc phần Safe Args dưới đây.

      @Composable
      fun SampleNavHost(
          navController: NavHostController
      ) {
          NavHost(navController = navController, startDestination = "first") {
              composable("first") {
                  FirstScreen(
                      onButtonClick = {
                          // findNavController().navigate(firstScreenToSecondScreenAction)
                          navController.navigate("second_screen_route")
                      }
                  )
              }
              composable("second") {
                  SecondScreen(
                      onIconClick = {
                          // findNavController().navigate(secondScreenToThirdScreenAction)
                          navController.navigate("third_screen_route")
                      }
                  )
              }
              // ...
          }
      }

  8. Xoá tất cả Mảnh, bố cục XML có liên quan, thành phần điều hướng không cần thiết và các tài nguyên khác, cũng như các phần phụ thuộc cũ của Mảnh và Điều hướng Jetpack.

Bạn có thể xem các bước tương tự với những thông tin chi tiết khác liên quan đến thành phần Điều hướng trong Compose trong tài liệu về Thiết lập.

Các trường hợp sử dụng phổ biến

Bất kể bạn đang sử dụng thành phần Điều hướng nào, các nguyên tắc điều hướng tương tự cũng được áp dụng.

Sau đây là các trường hợp sử dụng phổ biến khi di chuyển:

Để biết thêm thông tin chi tiết về các trường hợp sử dụng này, hãy xem bài viết Điều hướng bằng Compose.

Safe Args

Không giống như thành phần Điều hướng Jetpack, Navigation Compose (Thành phần điều hướng trong Compose) không hỗ trợ việc sử dụng trình bổ trợ Safe Args để tạo mã. Thay vào đó, bạn có thể đạt được an toàn về kiểu bằng Điều hướng trong Compose thông qua cấu trúc mã để đảm bảo an toàn về kiểu trong thời gian chạy.

Truy xuất dữ liệu phức tạp khi điều hướng

Navigation Compose dựa trên tuyến đường chuỗi và không giống như thành phần Điều hướng Jetpack, không hỗ trợ truyền Parcelables và Serializable tuỳ chỉnh dưới dạng đối số.

Bạn không nên chuyển các đối tượng dữ liệu phức tạp khi điều hướng. Thay vào đó, hãy truyền thông tin cần thiết tối thiểu, chẳng hạn như giá trị nhận dạng duy nhất hoặc một dạng mã nhận dạng khác làm đối số khi thực hiện thao tác điều hướng. Bạn nên lưu trữ các đối tượng phức tạp dưới dạng dữ liệu trong một nguồn đáng tin cậy, chẳng hạn như lớp dữ liệu. Để biết thêm thông tin, hãy xem phần Truy xuất dữ liệu phức tạp khi điều hướng.

Nếu Mảnh đang truyền các đối tượng phức tạp dưới dạng đối số, trước tiên, hãy cân nhắc việc tái cấu trúc mã theo cách cho phép lưu trữ và tìm nạp các đối tượng này từ lớp dữ liệu. Hãy xem kho lưu trữ Now in Android để biết ví dụ.

Các điểm hạn chế

Phần này mô tả các hạn chế hiện tại của Navigation Compose.

Di chuyển dần sang Navigation Compose

Hiện tại, bạn không thể sử dụng Navigation Compose trong khi vẫn sử dụng các Mảnh làm đích đến trong mã của mình. Để bắt đầu sử dụng Navigation Compose, tất cả đích đến của bạn đều cần phải là thành phần kết hợp. Bạn có thể theo dõi yêu cầu về tính năng này trên Công cụ theo dõi lỗi.

Ảnh động chuyển tiếp

Kể từ Navigation 2.7.0-alpha01, tính năng hỗ trợ thiết lập hiệu ứng chuyển đổi tuỳ chỉnh (trước đây là AnimatedNavHost) giờ đây sẽ được hỗ trợ trực tiếp trong NavHost. Hãy đọc ghi chú phát hành để biết thêm thông tin.

Tìm hiểu thêm

Để biết thêm thông tin về cách di chuyển sang Navigation Compose, hãy xem các tài nguyên sau:

  • Lớp học lập trình về Điều hướng trong Compose: Tìm hiểu các kiến thức cơ bản về Điều hướng trong Compose thông qua một lớp học thực hành lập trình.
  • Kho lưu trữ Now in Android: Một ứng dụng Android có đầy đủ chức năng được xây dựng hoàn toàn bằng Kotlin và Jetpack Compose, tuân theo các phương pháp hay nhất về thiết kế và phát triển Android, đồng thời có cả thành phần Điều hướng trong Compose.
  • Di chuyển Sunflower sang Jetpack Compose: Một bài đăng trên blog ghi lại hành trình di chuyển của ứng dụng mẫu Sunflower từ Khung hiển thị sang Compose, bao gồm cả việc di chuyển sang Navigation Compose.
  • Jetnews cho mọi màn hình: Một bài đăng trên blog ghi lại cách tái cấu trúc và di chuyển mẫu Jetnews để hỗ trợ tất cả màn hình bằng Jetpack Compose và Navigation Compose.