在AndroidX偏好设置中的OnBackPressedDispatcher错误。

huangapple go评论61阅读模式
英文:

Bug of OnBackPressedDispatcher in androidx preference

问题

以下是您提供的内容的翻译:

有一个导航链 MainFragment > SettingsFragment > SubSettingsFragment

navController.navigate(MainFragment.toSettingsFragment())
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Preference
        android:fragment=".SubSettingsFragment"
        app:summary="@string/pref_header_summary_permission"
        app:title="@string/pref_title_permission" />

</PreferenceScreen>

当我们位于 SubSettingsFragment 并按下返回按钮时,出现 MainFragmentSettingsFragment 被跳过。

PreferenceHeaderFragmentCompat 有一个根据 源代码 处理的 onBackPressedCallback。但由于某种原因它不起作用。

我们能将 NavController 的返回栈连接到 PreferenceHeaderFragmentCompat 吗?

更新 1

我找到了为什么 onBackPressedCallback 不起作用的原因。在官方源代码中,在 onViewCreated 中,来自上下文的调度程序为空。这就是为什么 addCallback 没有运行的原因。

@CallSuper
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    onBackPressedCallback = InnerOnBackPressedCallback(this)
    slidingPaneLayout.doOnLayout {
        onBackPressedCallback!!.isEnabled =
            slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen
    }
    childFragmentManager.addOnBackStackChangedListener {
        onBackPressedCallback!!.isEnabled = childFragmentManager.backStackEntryCount == 0
    }

    // this owner is null
    val onBackPressedDispatcherOwner = requireContext() as? OnBackPressedDispatcherOwner
    onBackPressedDispatcherOwner?.let {
        it.onBackPressedDispatcher.addCallback(
            viewLifecycleOwner,
            onBackPressedCallback!!
        )
    }
}

我创建了一个自定义的 PreferenceHeaderFragmentCompat,将 requireContext() 更改为 requireActivity(),它可以正常工作。从 SubSettingsFragment 返回按下返回按钮将弹出到 SettingsFragment

requireActivity().onBackPressedDispatcher.addCallback(
    viewLifecycleOwner,
    onBackPressedCallback!!
)

您知道为什么 requireContext() as? OnBackPressedDispatcherOwner 为空吗?

英文:

There are chain MainFragment > SettingsFragment > SubSettingsFragment:

navController.navigate(MainFragment.toSettingsFragment())
&lt;PreferenceScreen xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;&gt;

    &lt;Preference
        android:fragment=&quot;.SubSettingsFragment&quot;
        app:summary=&quot;@string/pref_header_summary_permission&quot;
        app:title=&quot;@string/pref_title_permission&quot; /&gt;

&lt;/PreferenceScreen&gt;

When we located at SubSettingsFragment and press back button, appears MainFragment. SettingsFragment skipped.

PreferenceHeaderFragmentCompat has onBackPressedCallback handle accoding source code. But for some reason don't work.

Can we connect backstack of NavController to PreferenceHeaderFragmentCompat?

Update 1

I found why onBackPressedCallback don't work. In official source code in onViewCreated, dispatcher from context is null. That's why addCallback isn't run.

    @CallSuper
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        onBackPressedCallback = InnerOnBackPressedCallback(this)
        slidingPaneLayout.doOnLayout {
            onBackPressedCallback!!.isEnabled =
                slidingPaneLayout.isSlideable &amp;&amp; slidingPaneLayout.isOpen
        }
        childFragmentManager.addOnBackStackChangedListener {
            onBackPressedCallback!!.isEnabled = childFragmentManager.backStackEntryCount == 0
        }

        // this owner is null
        val onBackPressedDispatcherOwner = requireContext() as? OnBackPressedDispatcherOwner
        onBackPressedDispatcherOwner?.let {
            it.onBackPressedDispatcher.addCallback(
                viewLifecycleOwner,
                onBackPressedCallback!!
            )
        }
    }

I create custom PreferenceHeaderFragmentCompat where change requireContext() to requireActivity() and it's works. Back pressed from SubSettingsFragment pop to SettingsFragment.

requireActivity().onBackPressedDispatcher.addCallback(
    viewLifecycleOwner,
    onBackPressedCallback!!
)

Do you know why requireContext() as? OnBackPressedDispatcherOwner is null?

答案1

得分: 0

问题出在官方的PreferenceHeaderFragmentCompatonViewCreated()方法中。Google已经修复了这个问题,将在未来的发布版本中发布(请参见问题)。

// 当我们使用Hilt注解时,此所有者为空 - AndroidEntryPoint
val onBackPressedDispatcherOwner = requireContext() as? OnBackPressedDispatcherOwner
onBackPressedDispatcherOwner?.let {
    it.onBackPressedDispatcher.addCallback(
        viewLifecycleOwner,
        onBackPressedCallback!!
    )
}
英文:

The problem was in onViewCreated() of official PreferenceHeaderFragmentCompat. Fixed by Google for future release (see issue).

// this owner is null when we use Hilt annotation - AndroidEntryPoint 
val onBackPressedDispatcherOwner = requireContext() as? OnBackPressedDispatcherOwner
onBackPressedDispatcherOwner?.let {
    it.onBackPressedDispatcher.addCallback(
        viewLifecycleOwner,
        onBackPressedCallback!!
    )
}

huangapple
  • 本文由 发表于 2023年6月12日 21:22:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76457115.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定