21

我开始在我的应用程序中使用导航组件,我面临以下问题。我的第一个片段是 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。知道如何解决这个问题吗?提前致谢。

4

6 回答 6

20

同样的问题发生在我身上,我设法通过将navigate方法包装在view?.post这样的调用中来解决它:

view?.post {
    findNavController().navigate(SplashFragmentDirections.actionSplashFragmentToLoginFragment())
}
于 2020-01-12T02:38:56.893 回答
9

当您尝试调用findNavController()已分离的片段时会导致问题,如果您使用的是 Kotlin,则可以像这样创建扩展函数

fun Fragment.findNavControllerSafely(): NavController? {
    return if (isAdded) {
        findNavController()
    } else {
        null
    }
}

然后在任何片段中使用它

findNavControllerSafely()?.navigate(/*pass here the nav directions>*/)

你也可以用 try/catch 包围它,但我不建议这样做,因为它会默默地捕捉/忽略其他可能有用的异常,尝试浏览源代码findNavController()以更好地了解抛出的异常类型

于 2020-09-22T22:42:27.000 回答
0

我也遇到过这个问题,知道出了什么问题非常令人困惑!

我发现这个 URL 对我帮助很大!:Android 导航组件问题

这个人建议在每个片段上创建一个函数,因为当使用 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)
于 2020-05-20T00:29:34.500 回答
0

我为这个问题创建了一个扩展,它基于片段生命周期和 kotlin 工作

fun NavController.lifeCycleNavigate(lifecycle :LifecycleCoroutineScope, resId :Int) =
    lifecycle.launchWhenResumed {
        navigate(resId)
    }

现在我们可以简单地将它与 navController 一起使用,就像这样

findNavController().lifeCycleNavigate(lifecycleScope  , R.id.destination )
于 2021-12-07T06:31:57.863 回答
0

我今天面临同样的问题。问题在于导入了错误的文件。实际上有3个文件可以导入。

  1. 导入 androidx.navigation.fragment.findNavController

    这说 findNavController()

  2. 导入 androidx.navigation.Navigation.findNavController

    这说 findNavController(Activity, Int)

  3. 导入 androidx.navigation.fragment.NavHostFragment.findNavController

    这说 findNavController(Fragment)

如果我使用第二个,它会给出错误片段未附加/关联/到活动。(不记得确切的错误)

如果我使用第三个,我会遇到与@Gabrielle 相同的错误

所以,对我来说,第一个工作得很好,因为它不需要 Activity 或 Fragment。

于 2021-07-22T19:41:38.273 回答
0

对我来说,问题是由于配置更改而恢复后的片段是片段管理器在片段中无效,所以我必须直接从这样的活动中获取它:

activity?.findNavController(R.id.nav_host_fragment)?.navigate(....)

或者

activity?.supportFragmentManager?.setFragmentResultListener(.....)
于 2021-03-03T16:21:05.187 回答