片段 XXX 未与片段管理器关联
Posted
技术标签:
【中文标题】片段 XXX 未与片段管理器关联【英文标题】:Fragment XXX not associated with a fragment manager片段 XXX 未与片段管理器关联 【发布时间】:2019-09-26 06:10:00 【问题描述】:我开始在我的应用程序中使用导航组件,但遇到了以下问题。
我的第一个片段是 LoginFragment。成功登录后,会显示 mainFragment。我希望当用户在 mainFragment 上并按后退按钮不返回 loginFragment 时。为此,我在 nav_graph 中添加了这两行:app:popUpTo="@+id/lovable_app_navigation"
和 app:popUpToInclusive="true"
,效果很好。这是我的导航图:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/app_navigation"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name="com.xxx.LoginFragment"
android:label="LoginFragment"
tools:layout="@layout/login_fragment">
<action
android:id="@+id/dashboard_action"
app:destination="@id/mainFragment"
app:launchSingleTop="true"
app:popUpTo="@+id/app_navigation"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="@+id/mainFragment"
android:name="com.xxx.MainFragment"
android:label="MainFragment"
tools:layout="@layout/main_fragment">
<action
android:id="@+id/logout_action"
app:destination="@id/loginFragment"
app:launchSingleTop="true"
app:popUpTo="@+id/app_navigation"
app:popUpToInclusive="true"/>
</fragment>
<action
android:id="@+id/action_global_loginFragment"
app:destination="@id/loginFragment" />
</navigation>
问题是,一段时间后,当我的会话到期时,用户在应用程序中的哪个位置,在哪个片段中都无关紧要,我必须在所有堆栈上显示 LoginFragment。我为此 action_global_loginFragment
创建了一个全局操作。问题是当我导航到 LoginFragment 时出现此错误:
java.lang.IllegalStateException: Fragment LoginFragment1d6bd24 (829a6832-3480-4bcb-a3f6-7e2ba214d3ca) not associated with a fragment manager.
如果我删除 popUpTo
和 popUpToInclusive
它可以正常工作,但是后退按钮功能会受到影响,从 mainFragment 会返回到 loginFragment。
知道如何解决这个问题吗?
提前致谢。
【问题讨论】:
【参考方案1】:同样的问题发生在我身上,我设法通过将 navigate
方法包装在 view?.post
调用中来解决它,如下所示:
view?.post
findNavController().navigate(SplashFragmentDirections.actionSplashFragmentToLoginFragment())
【讨论】:
这对我有用。基本上,您正在检查片段是否仍然附加这样做。如果没有,是因为您已经导航了。非常感谢。 @Amg91 这个解决方案有效,但为什么我们可以控制已经收集的垃圾/backPressed 片段?【参考方案2】:当您尝试在已分离的片段上调用 findNavController()
时会导致问题,如果您使用的是 Kotlin,您可以像这样创建扩展函数
fun Fragment.findNavControllerSafely(): NavController?
return if (isAdded)
findNavController()
else
null
然后在任何片段中使用它
findNavControllerSafely()?.navigate(/*pass here the nav directions>*/)
你也可以用 try/catch 包围它,但我不建议这样做,因为它会默默地捕捉/忽略其他可能有用的异常,尝试浏览 findNavController()
的源代码以获得更好的感觉抛出的异常
【讨论】:
“我不推荐这样做,因为它会默默地捕获/忽略其他可能有用的异常”或者您可能只是捕获您感兴趣的异常... @FranMarzoa 是的,你是对的,完全错过了:D【参考方案3】:对我来说,问题是由于配置更改而恢复后的片段是片段管理器在片段中无效,所以我必须直接从这样的活动中获取它:
activity?.findNavController(R.id.nav_host_fragment)?.navigate(....)
或
activity?.supportFragmentManager?.setFragmentResultListener(.....)
【讨论】:
【参考方案4】:我今天也面临同样的问题。 问题在于导入了错误的文件。 实际上有3个文件可以导入。
导入 androidx.navigation.fragment.findNavController
这就是 findNavController()
导入 androidx.navigation.Navigation.findNavController
这表示 findNavController(Activity, Int)
导入 androidx.navigation.fragment.NavHostFragment.findNavController
这表示 findNavController(Fragment)
如果我使用第二个,它会给出错误片段未附加/关联/到活动。 (不记得确切的错误)
如果我使用第三个,我会遇到与@Gabrielle 相同的错误
所以,对我来说,第一个工作得非常好,因为它不需要 Activity 或 Fragment。
【讨论】:
【参考方案5】:我也遇到过这个问题,不知道哪里出了问题!
我发现这个网址对我帮助很大!:Android Navigation Component Issue
这个人建议在每个片段上创建一个函数,因为当使用 findNavController() 的片段不是 NavHostFragment 或不在 NavHostFragment 中时,会抛出此异常。
fun Fragment.getFragmentNavController(@IdRes id: Int) = activity?.let
return@let Navigation.findNavController(it, id)
然后,您可以像这样使用 id 的所有导航实例:
getFragmentNavController(R.id.shipping_host_nav).navigate(R.id.id_of_host_nav)
【讨论】:
【参考方案6】:我为这个问题创建了一个扩展,它基于片段生命周期和 kotlin 工作
fun NavController.lifeCycleNavigate(lifecycle :LifecycleCoroutineScope, resId :Int) =
lifecycle.launchWhenResumed
navigate(resId)
现在我们可以像这样简单地将它与 navController 一起使用
findNavController().lifeCycleNavigate(lifecycleScope , R.id.destination )
【讨论】:
以上是关于片段 XXX 未与片段管理器关联的主要内容,如果未能解决你的问题,请参考以下文章