用户通过 返回导航 在屏幕之间向后导航。大多数 Android 设备都配有返回按钮(物理按钮、软件按钮或基于手势的按钮)。通常,您不应在应用中添加返回按钮。但是,兼容模式下的 Android Automotive OS (AAOS) 设备使用系统返回按钮。此按钮可处理导航,因此您无需添加自己的返回按钮。如需了解详情,请参阅 AAOS 兼容模式。
用户在您的应用中导航时,Android 会维护一个目的地的返回堆栈。这通常允许 Android 在按下“返回”按钮时正确导航到先前的目的地。但是,在某些情况下,您的应用可能需要实现自己的返回行为,以提供最佳用户体验。例如,在使用 WebView 时,您可能希望替换默认的“返回”按钮行为,以允许用户返回其网页浏览历史记录,而不是返回应用中的先前屏幕。
实现自定义返回导航
ComponentActivity 是 FragmentActivity 和 AppCompatActivity 的基类,它允许您通过使用其 OnBackPressedDispatcher 来控制“返回”按钮的行为,您可以通过调用 getOnBackPressedDispatcher() 来检索它。
OnBackPressedDispatcher 控制“返回”按钮事件如何分派到一个或多个 OnBackPressedCallback 对象。OnBackPressedCallback 的构造函数接受一个布尔值,用于设置初始启用状态。只有当回调处于启用状态(即 isEnabled() 返回 true)时,调度程序才会调用回调的 handleOnBackPressed() 来处理“返回”按钮事件。您可以通过调用 setEnabled() 来更改启用状态。
回调通过 addCallback 方法添加。强烈建议使用接受 LifecycleOwner 的 addCallback() 方法。这可确保只有当 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() 提供多个回调。在这种情况下,回调将按照添加的逆序调用 - 最后添加的回调将首先有机会处理“返回”按钮事件。例如,如果您按顺序添加了三个名为 one、two 和 three 的回调,它们将分别以 three、two 和 one 的顺序调用。
回调遵循 责任链模式。链中的每个回调只有在前一个回调未启用时才会被调用。这意味着在上述示例中,只有当回调 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都会始终被调用。