提供自定义返回导航

返回导航是指用户通过之前访问过的屏幕的历史记录实现返回操作的方式。所有 Android 设备都为此类导航提供了返回按钮,因此您不应向应用界面添加返回按钮。此按钮可以是物理按钮,也可以是软件按钮,具体取决于用户的 Android 设备。

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

实现自定义返回导航

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

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

回调通过 addCallback 方法添加。强烈建议您使用 addCallback() 方法,该方法采用了 LifecycleOwner。这可以确保仅在 LifecycleOwnerLifecycle.State.STARTED 时添加 OnBackPressedCallback。此外,与注册的回调相关联的 LifecycleOwner 被销毁时,相应 activity 还会移除注册的回调。这不仅可以防止内存泄漏,还可以使其适用于生命周期短于该 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销毁时自动移除。

Activity onBackPressed()

如果您使用 onBackPressed() 处理返回按钮事件,我们建议您改用 OnBackPressedCallback。但是,如果您无法进行此项更改,请遵循以下规则:

  • 当您调用 super.onBackPressed() 时,系统对通过 addCallback 注册的所有回调进行评估。
  • 在 Android 12(API 级别 32)及更低版本中,始终调用 onBackPressed,而不考虑 OnBackPressedCallback 的任何已注册实例。