我开始在应用程序中使用导航组件,并且遇到以下问题。
我的第一个片段是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 LoginFragment{1d6bd24 (829a6832-3480-4bcb-a3f6-7e2ba214d3ca)} not associated with a fragment manager.
如果我删除popUpTo
和popUpToInclusive
可以正常工作,但是后退按钮功能会受到影响,从mainFragment会返回到loginFragment。
任何想法如何解决这个问题?
预先感谢。
答案 0 :(得分:8)
我遇到了同样的问题,我设法通过将navigate
方法包装在view?.post
调用中来解决了这个问题,
view?.post {
findNavController().navigate(SplashFragmentDirections.actionSplashFragmentToLoginFragment())
}
答案 1 :(得分:1)
当您尝试在已分离的片段上调用findNavController()
时,会导致此问题,如果您使用的是Kotlin,则可以像这样创建扩展功能
fun Fragment.findNavControllerSafely(): NavController? {
return if (isAdded) {
findNavController()
} else {
null
}
}
然后在任何片段中使用它
findNavControllerSafely()?.navigate(/*pass here the nav directions>*/)
您也可以在try / catch周围加上它,但我不建议您这样做,因为它会静默地捕获/忽略其他可能有用的异常,请尝试浏览findNavController()
的源代码以更好地了解引发的异常类型
答案 2 :(得分:0)
我也遇到了这个问题,很难知道怎么了!
我发现此网址对我有很大帮助!:Android Navigation Component Issue 由于当将findNavController()与非NavHostFragment或不在NavHostFragment内的片段一起使用时,此家伙建议在每个片段上创建一个函数。
fun Fragment.getFragmentNavController(@IdRes id: Int) = activity?.let {
return@let Navigation.findNavController(it, R.id)
}
然后,您可以将所有具有ID的导航实例都如下所示:
getFragmentNavController(R.id.shipping_host_nav).navigate(R.id.id_of_host_nav)
答案 3 :(得分:0)
对我来说,问题是由于配置更改而恢复后的片段是片段管理器在片段中无效,所以我必须直接从这样的活动中获取它:
activity?.findNavController(R.id.nav_host_fragment)?.navigate(....)
或
activity?.supportFragmentManager?.setFragmentResultListener(.....)
答案 4 :(得分:0)
我今天遇到了同样的问题。 问题在于导入了错误的文件。 实际上可以导入 3 个文件。
导入 androidx.navigation.fragment.findNavController
这是 findNavController()
导入 androidx.navigation.Navigation.findNavController
这表示 findNavController(Activity, Int)
导入 androidx.navigation.fragment.NavHostFragment.findNavController
这是 findNavController(Fragment)
如果我使用了第二个,它会给出一个错误 Fragment not attach/ associated with/to an Activity。 (不记得确切的错误)
如果我使用第三个,我会遇到与@Gabrielle 相同的错误
所以,对我来说,第一个工作得非常好,因为它不需要 Activity 或 Fragment。