Cung cấp tính năng điều hướng quay lại tuỳ chỉnh

Người dùng lùi lại qua các màn hình bằng tính năng điều hướng quay lại. Hầu hết các thiết bị Android đều có nút quay lại (vật lý, phần mềm hoặc dựa trên cử chỉ). Thông thường, bạn không nên thêm nút quay lại vào ứng dụng. Tuy nhiên, các thiết bị Android Automotive OS (AAOS) ở chế độ tương thích sẽ sử dụng nút quay lại của hệ thống. Nút này xử lý hoạt động điều hướng, vì vậy, bạn không cần thêm nút quay lại của riêng mình. Để biết thông tin chi tiết, hãy xem bài viết Chế độ tương thích AAOS.

Android duy trì một ngăn xếp lui của các đích đến khi người dùng di chuyển trong ứng dụng. Điều này thường cho phép Android điều hướng chính xác đến các đích đến trước đó khi nhấn nút Quay lại. Tuy nhiên, trong một số trường hợp, có thể ứng dụng cần phải triển khai thao tác Quay lại để mang lại trải nghiệm người dùng tốt nhất. Ví dụ: khi sử dụng WebView, bạn có thể ghi đè hành vi mặc định của nút Quay lại để cho phép người dùng quay lại thông qua nhật ký duyệt web thay vì các màn hình trước đó trong ứng dụng.

Triển khai tính năng điều hướng quay lại tuỳ chỉnh trong Compose

Trong Jetpack Compose, bạn có thể xử lý tính năng điều hướng quay lại tuỳ chỉnh bằng cách sử dụng hàm composable BackHandler.

Khi sử dụng Navigation Compose, bạn thường dùng NavController.navigateUp() hoặc NavController.popBackStack() để chuyển đến màn hình trước đó trong ngăn xếp lui. Tuy nhiên, BackHandler rất hữu ích trong trường hợp bạn muốn triển khai hành vi tuỳ chỉnh khi người dùng nhấn nút quay lại của hệ thống hoặc dùng cử chỉ quay lại. Ví dụ: nếu đang hiển thị WebView trong ứng dụng, bạn có thể cho phép người dùng quay lại thông qua nhật ký duyệt web khi họ nhấn nút quay lại của hệ thống.

Cách sử dụng cơ bản

Dưới đây là ví dụ cho biết cách chặn sự kiện quay lại để kiểm soát trạng thái tuỳ chỉnh (chẳng hạn như thu gọn một bảng điều khiển):

@Composable
fun MyScreen() {
    var isExpanded by remember { mutableStateOf(false) }

    // Intercept the back button or gesture only when isExpanded is true
    BackHandler(enabled = isExpanded) {
        // Collapsing the content disables this handler, so it does not
        // receive the next back event.
        isExpanded = false
    }

    if (isExpanded) {
        Text("Expanded content. Go back to collapse it.")
    } else {
        Button(onClick = { isExpanded = true }) {
            Text("Expand")
        }
    }
}

Chặn cây thành phần kết hợp

Nếu bạn có nhiều hàm composable BackHandler đã bật ở các cấp khác nhau của cây thành phần kết hợp, thì chỉ hàm composable trong cùng mới chặn sự kiện quay lại.

Triển khai tính năng điều hướng quay lại tuỳ chỉnh bằng Khung hiển thị

ComponentActivity, lớp cơ sở cho FragmentActivity và AppCompatActivity, cho phép bạn kiểm soát hành vi của nút Quay lại bằng cách sử dụng OnBackPressedDispatcher. Bạn có thể truy xuất này bằng cách gọi getOnBackPressedDispatcher().

The OnBackPressedDispatcher kiểm soát cách các sự kiện của nút Quay lại được gửi đến một hoặc nhiều đối tượng OnBackPressedCallback. Hàm khởi tạo cho OnBackPressedCallback nhận một giá trị boolean cho trạng thái đã bật ban đầu. Chỉ khi một lệnh gọi lại được bật (ví dụ: khi isEnabled() trả về true), trình điều phối mới gọi handleOnBackPressed() của lệnh gọi lại để xử lý sự kiện của nút Quay lại. Bạn có thể thay đổi trạng thái đã kích hoạt đó bằng cách gọi setEnabled().

Lệnh gọi lại được thêm bằng các phương thức addCallback. Sử dụng phương thức addCallback() nhận một LifecycleOwner. Bằng cách này, OnBackPressedCallback chỉ được thêm khi LifecycleOwner là Lifecycle.State.STARTED. Hoạt động này cũng xoá các lệnh gọi lại đã đăng ký khi LifecycleOwner được liên kết bị huỷ. Điều này giúp ngăn ngừa tình trạng rò rỉ bộ nhớ và phù hợp để sử dụng trong các mảnh hoặc chủ sở hữu vòng đời khác có thời gian tồn tại ngắn hơn hoạt động.

Dưới đây là ví dụ về cách triển khai lệnh gọi lại:

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }
    ...
}

Bạn có thể cung cấp nhiều lệnh gọi lại bằng cách sử dụng addCallback(). Khi thực hiện việc này, các lệnh gọi lại sẽ được gọi theo thứ tự ngược lại với thứ tự mà chúng được thêm vào. Lệnh gọi lại được thêm vào sau cùng là lệnh gọi lại đầu tiên có cơ hội xử lý sự kiện của nút Quay lại. Ví dụ: nếu bạn thêm 3 lệnh gọi lại có tên lần lượt là one, two và three, thì chúng sẽ được gọi theo thứ tự three, two và one.

Lệnh gọi lại tuân theo mẫu Chuỗi trách nhiệm. Mỗi lệnh gọi lại trong chuỗi chỉ được gọi nếu lệnh gọi lại trước đó chưa được bật. Điều này có nghĩa là trong ví dụ trước, lệnh gọi lại two chỉ được gọi nếu lệnh gọi lại three chưa được bật. Lệnh gọi lại one chỉ được gọi nếu lệnh gọi lại two chưa được bật và mẫu này tiếp tục cho mọi lệnh gọi lại bổ sung.

Xin lưu ý rằng khi được thêm bằng cách sử dụng addCallback(), lệnh gọi lại sẽ không được thêm vào chuỗi trách nhiệm cho đến khi LifecycleOwner chuyển sang trạng thái Lifecycle.State.STARTED.

Bạn nên thay đổi trạng thái đã bật trên lệnh gọi lại cho các thay đổi tạm thời vì chế độ này sẽ duy trì thứ tự mô tả ở trên. Điều này rất quan trọng khi đăng ký lại các lệnh gọi lại trên nhiều chủ sở hữu vòng đời lồng nhau.

Nếu bạn muốn xoá hoàn toàn lệnh gọi lại, hãy gọi remove(). Thông thường, bạn không cần làm việc này vì các lệnh gọi lại sẽ tự động bị xoá khi LifecycleOwner được liên kết bị huỷ.