提供自定义返回导航

用户通过 返回导航 在屏幕之间向后导航。大多数 Android 设备都配有返回按钮(物理按钮、软件按钮或基于手势的按钮)。通常,您不应在应用中添加返回按钮。但是,兼容模式下的 Android Automotive OS (AAOS) 设备使用系统返回按钮。此按钮可处理导航,因此您无需添加自己的返回按钮。如需了解详情,请参阅 AAOS 兼容模式

用户在您的应用中导航时,Android 会维护一个目的地的返回堆栈。这通常允许 Android 在按下“返回”按钮时正确导航到先前的目的地。但是,在某些情况下,您的应用可能需要实现自己的返回行为,以提供最佳用户体验。例如,在使用 WebView 时,您可能希望替换默认的“返回”按钮行为,以允许用户返回其网页浏览历史记录,而不是返回应用中的先前屏幕。

实现自定义返回导航

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

OnBackPressedDispatcher 控制“返回”按钮事件如何分派到一个或多个 OnBackPressedCallback 对象。OnBackPressedCallback 的构造函数接受一个布尔值,用于设置初始启用状态。只有当回调处于启用状态(即 isEnabled() 返回 true)时,调度程序才会调用回调的 handleOnBackPressed() 来处理“返回”按钮事件。您可以通过调用 setEnabled() 来更改启用状态。

回调通过 addCallback 方法添加。强烈建议使用接受 LifecycleOwneraddCallback() 方法。这可确保只有当 LifecycleOwner 处于 Lifecycle.State.STARTED 状态时,才添加 OnBackPressedCallback。当其关联的 LifecycleOwner 被销毁时,Activity 还会移除已注册的回调,这可以防止内存泄漏,并使其适用于 Fragment 或其他生命周期短于 Activity 的生命周期所有者。

以下是一个回调实现示例

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销毁时会自动移除。

Activity onBackPressed()

如果您正在使用 onBackPressed() 处理“返回”按钮事件,我们建议改用 OnBackPressedCallback。但是,如果您无法进行此更改,则适用以下规则

  • 当您调用 super.onBackPressed() 时,所有通过 addCallback 注册的回调都会被评估。
  • 在 Android 12(API 级别 32)及更低版本中,无论是否存在任何 OnBackPressedCallback 的注册实例,onBackPressed 都会始终被调用。