提供自定义返回导航

用户可以使用返回导航在界面之间向后导航。大多数 Android 设备都有返回按钮,可以是实体按钮、软件按钮,也可以通过手势操作。通常情况下,您不应向应用添加返回按钮。不过,处于兼容模式的 Android Automotive OS (AAOS) 设备会使用系统返回按钮。此代码会处理导航,因此您无需添加自己的导航代码。如需了解详情,请参阅 AAOS 兼容性模式

用户在您的应用中导航时,Android 会维护目的地的返回堆栈。这样,当用户按返回按钮时,Android 通常可以正确地导航到之前的目的地。不过,在少数情况下,您的应用可能需要实现自己的“返回”行为,以便提供最佳用户体验。例如,使用 WebView 时,您可能需要替换默认返回按钮行为,以允许用户通过其网页浏览记录(而非应用中之前访问过的屏幕)返回。

在 Compose 中实现自定义返回导航

在 Jetpack Compose 中,您可以使用 BackHandler 可组合项处理自定义返回导航。

使用 Navigation Compose 时,您通常使用 NavController.navigateUp()NavController.popBackStack() 导航到返回堆栈中的上一个界面。不过,在您希望在用户按系统返回按钮或使用返回手势时实现自定义行为的情况下,BackHandler 非常有用。例如,如果您要在应用中显示 WebView,则可能希望允许用户在按系统返回按钮时通过浏览记录返回。

如果您在可组合项树的不同级别有多个已启用的 BackHandler 可组合项,则只有最内层的可组合项会拦截返回事件。

使用 View 实现自定义返回导航

ComponentActivityFragmentActivityAppCompatActivity 的基类,通过使用它的 OnBackPressedDispatcher(可通过调用 getOnBackPressedDispatcher() 检索),您可以控制返回按钮行为。

OnBackPressedDispatcher 控制将返回按钮事件分派给一个或多个 OnBackPressedCallback 对象的方式。OnBackPressedCallback 的构造函数利用布尔值指示初始启用状态。仅当回调处于启用状态时(例如 isEnabled() 返回 true 时),调度程序才会调用回调的 handleOnBackPressed() 来处理返回按钮事件。您可以通过调用 setEnabled() 更改启用状态。

回调通过 addCallback 方法添加。使用 addCallback() 方法,该方法接受 LifecycleOwner。这样,仅当 LifecycleOwnerLifecycle.State.STARTED 时,系统才会添加 OnBackPressedCallback。此外,该 activity 还会在与注册回调相关联的 LifecycleOwner 被销毁时移除注册回调。这不仅可以防止内存泄露,还可以使其适用于生命周期短于该 activity 的 fragment 或其他生命周期所有者。

以下是一个回调实现示例:

Kotlin

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
    }
    ...
}

Java

public class MyFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This callback will only be called when MyFragment is at least Started.
        OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
            @Override
            public void handleOnBackPressed() {
                // Handle the back button event
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

        // The callback can be enabled or disabled here or in handleOnBackPressed()
    }
    ...
}

您可以使用 addCallback() 提供多个回调。如果这样做,回调的调用顺序与其添加顺序相反,即最后添加的回调是第一个有机会处理返回按钮事件的回调。例如,如果您按顺序添加了三个名为 onetwothree 的回调,它们的调用顺序分别为 threetwoone

回调遵循责任链模式。责任链中的每个回调仅在前面的回调处于未启用状态时调用。这意味着,在前面的示例中,仅当 three 回调处于未启用状态时,系统才会调用 two 回调。仅当 two 回调处于未启用状态时,系统才会调用 one 回调,以此类推。

请注意,如果回调是通过 addCallback() 添加的,在 LifecycleOwner 进入 Lifecycle.State.STARTED 状态之前,它不会添加到责任链中。

对于临时性更改,强烈建议您更改 OnBackPressedCallback 的启用状态,因为它会维护上文所述的排序。如果您在多个不同的嵌套生命周期所有者上注册了回调,这一点尤为重要。

但是,如果您想要彻底移除 OnBackPressedCallback,应调用 remove()。不过,这通常是没有必要的,因为回调会在与其关联的 LifecycleOwner销毁时自动移除。