onBackPressedDispatcher.onBackPressed() 与 backPressedCallback.handleOnBackPressed()

onBackPressedDispatcher.onBackPressed() vs backPressedCallback.handleOnBackPressed()

提问人:Bitwise DEVS 提问时间:6/27/2022 最后编辑:NeohBitwise DEVS 更新时间:9/27/2022 访问量:13105

问:

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

例:

override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (item.itemId) {

            // Handle default back arrow click
            android.R.id.home -> {
                onBackPressed()
            }
 ...

我们可以创建并添加这样的内容。OnBackPressedCallbackonBackPressedDispatcher

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()
        }
    }

然后将旧的替换为onBackPressed

// Handle default back arrow click
            android.R.id.home -> {
                backPressedCallback.handleOnBackPressed()
            }

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

onBackPressedDispatcher.onBackPressed()

此方法是否对 中添加的每个方法进行迭代?OnBackPressedCallbackonBackPressedDispatcher

安卓 android-jetpack android-jetpack-navigation onbackpressed android-提拉米苏

评论

0赞 Alvin Dizon 7/4/2022
我的理解是,将一个注册到一个活动的,取代了通常放在 .另一方面,碎片使用OnBackInvokedCallbackonBackInvokedDispatcheronBackPressed()onBackPressedDispatcher/OnBackPressedCallback
0赞 Bitwise DEVS 7/6/2022
@AlvinDizon不,基于这个答案,一个没有向后兼容性,而另一个在内部处理它。
0赞 Alvin Dizon 7/6/2022
我明白了,谢谢你发帖
0赞 Alvin Dizon 7/12/2022
如果我尝试在活动上使用 onBackPressedCallback,在第一次反向按下时什么也没发生,第二次反压是事情正常的时候,所以我不确定这里发生了什么
0赞 Bitwise DEVS 7/13/2022
@AlvinDizon有很多可能 onBackPressedCallback 不起作用,首先是您可能将 LifecycleOwner 传入 .这可能会导致一些问题,例如当您的活动转到 onPause 和 onStop 时,因为另一个 Activity 在其上方打开或应用程序要最小化,在这种情况下,添加的回调将在内部删除。其他可能的原因是您在初始化期间设置了 false 或将回调设置为 false,这也阻止了它的工作。addCallbackOnBackPressedCallback(false).isEnabled

答:

9赞 Pavlo Ostasha 9/23/2022 #1

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

    @Override
    @MainThread
    public void onBackPressed() {
        mOnBackPressedDispatcher.onBackPressed();
    }

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

public void onBackPressed()

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

如果调用此方法时 hasEnabledCallbacks 为 false,则将触发构造函数设置的回退 Runnable。

所以你在这里的策略可能是这样的 - 如果你需要在后退导航之前执行一些特定的东西 - 你把它添加到回调中。如果不需要特殊行为 - 你可以直接调用 - 它仍然会调用最近添加的(当然如果有的话)回调方法,但如果它是空的 - 后面就可以正常工作了。handleOnBackPressedmOnBackPressedDispatcher.onBackPressed()

但是,您需要记住,方法有两个覆盖:addCallback

addCallback(@NonNull OnBackPressedCallback onBackPressedCallback)

public void addCallback(
    @NonNull LifecycleOwner owner,
    @NonNull OnBackPressedCallback onBackPressedCallback
)

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

更多信息 这里这里.

评论

0赞 Bitwise DEVS 9/23/2022
非常感谢,我使用了错误的术语,它实际上不是迭代,而是堆栈。我所做的是在恢复片段时添加一个回调,并在它停止时将其删除。我还删除了活动回调的生命周期,因为提供它会将后退控制从其片段中移开,这通常不是首选行为。
0赞 IgorGanapolsky 6/8/2023
什么??mOnBackPressedDispatcher
1赞 Pavlo Ostasha 6/9/2023
@IgorGanapolsky就在这里。基本上,创建用于封装后向导航并将其与 UI 分离的抽象。如果我没记错的话,它首次出现在 AndroidX 库中。它负责活动和片段中的后退导航,在整个后退导航例程中为所需的操作提供更大的灵活性和空间,而不考虑后退事件的来源。比以前更冗长,但也更舒适恕我直言。
0赞 Kevin Meneses Palta 7/1/2023
这个onBackPressedDispatcher是否与旧版本的Android SDK向后兼容?