Di chuyển Jetpack Navigation sang Navigation Compose

API Điều hướng Compose cho phép bạn di chuyển giữa các thành phần kết hợp trong ứng dụng Compose, đồng thời tận dụng các 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 thành phần Điều hướng Compose trong hoạt động di chuyển giao diện người dùng lớn hơn dựa trên Khung hiển thị sang Jetpack Compose.

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

Bạn có thể di chuyển sang Navigation Compose khi có thể thay thế tất cả các Mảnh bằng 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ả các đích đến điều hướng phải là thành phần kết hợp để bật tính năng 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 Khung hiển thị tương tác và cơ sở mã của Compose. 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 tính nă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 vẫn còn các Mảnh để lưu trữ nội dung có thể 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 của chúng tôi hay áp dụng phương pháp khác, bạn đều sẽ đạt đến một điểm mà tại đó tất cả đích điều hướng đều là thành phần kết hợp màn hình, trong đó các 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 đang 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 sẽ không yêu cầu tái cấu trúc lớn 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ế thông tin thiết lập của Bố cục khung 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 ở vị trí mà tất cả các thành phần kết hợp cần tham chiếu đến đều có quyền truy cập vào đó (thường nằm trong thành phần kết hợp App). Phương pháp này tuân theo 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 để di chuyển 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ừ các 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, thì 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 của tính năng này với 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ả các lệnh gọi điều hướng findNavController() bằng lệnh gọi navController và truyền các lệnh gọi này dưới dạng sự kiện điều hướng đến từng màn hình thành phần 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ữ cho navController là nguồn đáng tin cậy duy nhất.

    1. Nếu trước đây bạn đã từng dùng trình bổ trợ Safe Args để tạo hướng dẫn 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 riêng biệ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 các đối số.
    3. Để biết an toàn về kiểu trong Navigation Compose, hãy đọ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 nhiều 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ề cách 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ự sẽ á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ư Jetpack Navigation, tính năng Navigation Compose không hỗ trợ 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 với Navigation Compose thông qua việc định 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 và không giống như Jetpack Navigation, không hỗ trợ truyền các Parcelables và Serializables tuỳ chỉnh dưới dạng đối số.

Bạn không nên truyề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 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 di chuyển.

Nếu các 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 tái cấu trúc mã của bạn 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 giới hạn hiện tại đối với Navigation Compose.

Di chuyển dần sang Navigation Compose

Hiện tại, bạn không thể dùng Navigation Compose trong khi vẫn dùng các Mảnh làm đích đến trong mã của mình. Để bắt đầu sử dụng thành phần Điều hướng trong Compose, mọi đích đến của bạn 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, chúng tôi hiện đã hỗ trợ trực tiếp việc thiết lập hiệu ứng chuyển đổi tuỳ chỉnh (trước đây là AnimatedNavHost) 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ề việc di chuyển sang thành phần Điều hướng trong Compose, hãy xem các tài nguyên sau:

  • Lớp học lập trình về thành phần Điều hướng trong Compose: Tìm hiểu kiến thức cơ bản về Điều hướng trong Compose qua 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 thủ các phương pháp hay nhất về thiết kế và phát triển Android, đồng thời có tính năng Navigation Compose.
  • Migrating Sunflower to Jetpack 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 quá trình tái cấu trúc và di chuyển mẫu Jetnews để hỗ trợ mọi màn hình bằng Jetpack Compose và Navigation Compose.