onBackPressedDispatcher.onBackPressed() 与 backPressedCallback.handleOnBackPressed()

Bit*_*EVS 13 android onbackpressed android-jetpack android-jetpack-navigation android-tiramisu

由于从 Android 33 开始旧版本Activity.onBackPressed()已被弃用,那么以编程方式调用它的更好方法是什么?

例子:

override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {

            // Handle default back arrow click
            android.R.id.home -> {
                onBackPressed()
            }
 ...
Run Code Online (Sandbox Code Playgroud)

我们可以创建并添加这样的OnBackPressedCallback内容onBackPressedDispatcher

onBackPressedDispatcher.addCallback(
            this, // Lifecycle owner
            backPressedCallback
        )

private val backPressedCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            if (viewPager.currentItem != 0)
                viewPager.setCurrentItem(0, true)
            else
                finish()
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后将旧的替换onBackPressed

// Handle default back arrow click
            android.R.id.home -> {
                backPressedCallback.handleOnBackPressed()
            }
Run Code Online (Sandbox Code Playgroud)

但我看到了这个公共方法onBackPressedDispatcher,想知道是否可以用它来代替。

onBackPressedDispatcher.onBackPressed()
Run Code Online (Sandbox Code Playgroud)

此方法是否会迭代OnBackPressedCallback中添加的每个内容onBackPressedDispatcher

Pav*_*sha 9

所以基本上onBackPressedDispatcher.onBackPressed()是相同的Activity.onBackPressed(),如果您不关心精确导航,您可以以相同的方式使用它。我怎么知道呢?ComponentActivity- 好吧,你可以看到(基本上是你正在使用的常规 Activity 的父级)的源代码,它onBackPressed()看起来像这样:

    @Override
    @MainThread
    public void onBackPressed() {
        mOnBackPressedDispatcher.onBackPressed();
    }
Run Code Online (Sandbox Code Playgroud)

关于它调用回调队列 - 你也是正确的,但它不是迭代它 - 而是只是调用最近的一个 - 一次一个(每次后按或每次onBackPressed()调用触发),文档指出:

public void onBackPressed()

以与添加回调相反的顺序触发对当前添加的回调的调用。仅当最近添加的回调不是时,enabled才会调用任何先前添加的回调。

如果调用该方法时 hasEnabledCallbacks 为 false,the constructor则将触发所设置的后备 Runnable。

因此,您的策略可能是这样的 - 如果您需要在返回导航之前执行一些特定的内容 - 您将其添加到handleOnBackPressed回调中。如果不需要特殊行为 - 您只需调用mOnBackPressedDispatcher.onBackPressed()- 它仍然会调用最近添加的(当然如果有的话)回调方法,但如果它是空的 - 后面会正常工作。

但您需要记住,有两种addCallback方法的重写:

addCallback(@NonNull OnBackPressedCallback onBackPressedCallback)
Run Code Online (Sandbox Code Playgroud)

public void addCallback(
    @NonNull LifecycleOwner owner,
    @NonNull OnBackPressedCallback onBackPressedCallback
)
Run Code Online (Sandbox Code Playgroud)

在前者中 - 当您需要remove不再执行回调时,您必须自己调用回调来处理回调队列。在后者中,LifecycleOwner状态更改必须为您处理所有需要的东西。

更多信息请点击这里这里