提供自定义后退导航

后退导航 是用户如何通过之前访问的屏幕历史记录向后移动。所有 Android 设备都为此类导航提供后退按钮,因此您不应在应用的 UI 中添加后退按钮。根据用户的 Android 设备,此按钮可能是物理按钮或软件按钮。

当用户在您的应用程序中导航时,Android 会维护一个包含目的地的后退堆栈。这通常使 Android 能够在按下后退按钮时正确导航到以前的目的地。但是,在某些情况下,您的应用可能需要实现自己的后退行为才能提供最佳的用户体验。例如,当使用WebView 时,您可能希望覆盖默认的后退按钮行为,以允许用户通过其网页浏览历史记录导航,而不是您应用中的上一个屏幕。

实施自定义后退导航

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

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

回调是通过 addCallback 方法添加的。强烈建议使用 addCallback() 方法,该方法接受一个 LifecycleOwner。这确保了 OnBackPressedCallback 仅在 LifecycleOwnerLifecycle.State.STARTED 时添加。活动还会在关联的 LifecycleOwner 被销毁时删除注册的回调,这可以防止内存泄漏,并使其适合在生命周期比活动更短的片段或其他生命周期所有者中使用。

以下是一个示例回调实现

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销毁 时,回调会自动删除。

活动 onBackPressed()

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

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