android-fragments 导航组件:IllegalStateException片段未与片段管理器关联

d5vmydt9  于 2022-11-13  发布在  Android
关注(0)|答案(7)|浏览(193)

我使用的是导航组件版本2.1.0-rc01,我使用
Navigation.findNavController(it).navigate(R.id.action_participants)
在第二次浏览相同的屏幕后,我可以看到第二个片段,但我收到了一个异常。我启用了FragmentManager上的日志,似乎有一个相同片段的不同示例没有附加,导致错误
你知道为什么导航组件创建了另一个没有附加的片段的示例吗?有什么方法可以得到附加的片段吗?

2019-08-15 16:59:30.895 30041-30041/com.app.debug D/FragmentManager:   mName=3-2131361912 mIndex=-1 mCommitted=false
2019-08-15 16:59:30.895 30041-30041/com.app.debug D/FragmentManager:   mEnterAnim=#7f01001e mExitAnim=#7f01001f
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:   mPopEnterAnim=#7f010020 mPopExitAnim=#7f010021
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:   Operations:
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:     Op #0: REPLACE StaffBookingDetailsFragment{82e8301 (97f79b28-d8c1-432a-9e1c-3a781dd42434) id=0x7f0a01c5}
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:   enterAnim=#7f01001e exitAnim=#7f01001f
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:   popEnterAnim=#7f010020 popExitAnim=#7f010021
2019-08-15 16:59:30.896 30041-30041/com.app.debug D/FragmentManager:     Op #1: SET_PRIMARY_NAV StaffBookingDetailsFragment{82e8301 (97f79b28-d8c1-432a-9e1c-3a781dd42434) id=0x7f0a01c5}
2019-08-15 16:59:30.897 30041-30041/com.app.debug D/FragmentManager:   enterAnim=#7f01001e exitAnim=#7f01001f
2019-08-15 16:59:30.897 30041-30041/com.app.debug D/FragmentManager:   popEnterAnim=#7f010020 popExitAnim=#7f010021
2019-08-15 16:59:31.935 30041-30041/com.app.debug D/FragmentManager:   mName=4-2131362286 mIndex=-1 mCommitted=false
2019-08-15 16:59:31.935 30041-30041/com.app.debug D/FragmentManager:   Operations:
2019-08-15 16:59:31.936 30041-30041/com.app.debug D/FragmentManager:     Op #0: REPLACE ParticipantsFragment{fdd9ef9 (b7317713-b150-44a2-8b1c-47a0f8c52781) id=0x7f0a01c5}
2019-08-15 16:59:31.936 30041-30041/com.app.debug D/FragmentManager:     Op #1: SET_PRIMARY_NAV ParticipantsFragment{fdd9ef9 (b7317713-b150-44a2-8b1c-47a0f8c52781) id=0x7f0a01c5}
2019-08-15 16:59:55.266 30041-30041/com.app.debug E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.app.debug, PID: 30041
    java.lang.IllegalStateException: Fragment ParticipantsFragment{b6e8bc7 (aa204a1e-5f3a-40c0-86f0-b5edab4b07eb)} not associated with a fragment manager.
        at androidx.fragment.app.Fragment.requireFragmentManager(Fragment.java:910)
        at com.app.bookings.participants.ParticipantsFragment.onParticipantActionClicked(ParticipantsFragment.kt:88)
        at com.app.databinding.ItemBindParticipantBindingImpl._internalCallbackOnClick(ItemBindParticipantBindingImpl.java:218)
        at com.app.generated.callback.OnClickListener.onClick(OnClickListener.java:11)
        at android.view.View.performClick(View.java:6669)
        at android.view.View.performClickInternal(View.java:6638)
        at android.view.View.access$3100(View.java:789)
        at android.view.View$PerformClick.run(View.java:26145)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6863)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
agyaoht7

agyaoht71#

确保片段已被垃圾收集/销毁。如果在onCreateView/onViewCreated等方法中注册了任何生命周期未知的已注册侦听器(不支持androidx.lifecycle.Lifecycle的侦听器),则不会对片段进行垃圾收集/销毁。确保在片段的onDestroyView()中取消注册此类侦听器。
例如:OnBackPressedDispatcher不是生命周期感知的。因此,它希望你在该片段被销毁时注销。如果它没有注销,那么它会保留一个引用,并在其他片段中按下back时被调用
我在内部调用findNavController().navigateUp()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)

             val onBackPressedCallback = object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    //some logic that needs to be run before fragment is destroyed
                    findNavController().navigateUp()
                }
            }
            requireActivity().onBackPressedDispatcher.addCallback(
                  onBackPressedCallback
            )
        }

如果您查看findNavController()的文档,
在不是[NavHostFragment]的片段上或在[NavHostFragment]内调用此方法将导致[IllegalStateException]
这就是为什么我
IllegalStateException片段未与片段管理器关联

解决方案

取消注册onDestroyView中的监听器

override fun onDestroyView() {
    super.onDestroyView()
    //unregister listener here
    onBackPressedCallback.isEnabled = false
    onBackPressedCallback.remove()
}
bttbmeg0

bttbmeg02#

如果添加生命周期所有者,则不需要在onDestroy文档中删除回调

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)

             val onBackPressedCallback = object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    findNavController().navigateUp()
                }
            }
            // ADD LIFECYCLE OWNER
            requireActivity().onBackPressedDispatcher.addCallback(this,
                  onBackPressedCallback
            )
        }
5anewei6

5anewei63#

您可以使用导航操作的XML属性popUpToInclusive="true"来指定是否弹出同一目标的旧示例。

hec6srdp

hec6srdp4#

导航.findNavController(它).navigate(R.id.操作_参与者)
代替上述地方
导航.findNavController(上下文).navigate(R.标识.操作_参与者)

rqdpfwrv

rqdpfwrv5#

我发现你使用了viewbinding这个类是在适配器中创建的,不能直接使用findnavcontroller你需要把当前的片段传递给适配器,然后把过去的片段传递给required类如果你需要activity也是如此把requireactivity传递给适配器再传递给required类

zi8p0yeb

zi8p0yeb6#

@Ramakrishna Joshi是正确的。在我的情况下,问题是我使用了

val menuHost: MenuHost = requireActivity()    
menuHost.addMenuProvider(menuProvider)

所以我必须像这样在onDestroyView上删除它

override fun onDestroyView() {
    val menuHost: MenuHost = requireActivity()
    menuHost.removeMenuProvider(menuProvider)
    super.onDestroyView()
}
slmsl1lt

slmsl1lt7#

经过进一步调查,我证实这只是碎片处理不当的副作用,现在已经解决了。

相关问题