英文:
Bug of OnBackPressedDispatcher in androidx preference
问题
以下是您提供的内容的翻译:
有一个导航链 MainFragment > SettingsFragment > SubSettingsFragment:
- 从
MainFragment到SettingsFragment通过 NavigationController
navController.navigate(MainFragment.toSettingsFragment())
- 从
Settings到SubSettingsFragment通过 PreferenceHeaderFragmentCompat
<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 并按下返回按钮时,出现 MainFragment。SettingsFragment 被跳过。
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:
- from
MainFragmenttoSettingsFragmentvia NavigationController
navController.navigate(MainFragment.toSettingsFragment())
- from
SettingstoSubSettingsFragmentvia PreferenceHeaderFragmentCompat
<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>
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 && 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
问题出在官方的PreferenceHeaderFragmentCompat的onViewCreated()方法中。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!!
)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论