<androidx.fragment.app.FragmentContainerView> 与 <fragment> 作为 NavHost 的视图

Posted

技术标签:

【中文标题】<androidx.fragment.app.FragmentContainerView> 与 <fragment> 作为 NavHost 的视图【英文标题】:<androidx.fragment.app.FragmentContainerView> vs <fragment> as a view for a NavHost 【发布时间】:2020-03-03 09:17:10 【问题描述】:

当使用androidx.fragment.app.FragmentContainerView 作为导航主机而不是常规的fragment 时,应用在方向更改后无法导航到目的地。

我收到以下错误: java.lang.IllegalStateException: no current navigation node

有没有我应该知道的正确使用它的问题,或者我使用导航组件的方式不正确?

带有视图的简单活动 xml:


...
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_
        android:layout_
        app:defaultNavHost="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        app:navGraph="@navigation/nav_simple" />
...

导航代码:

<?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/nav_legislator.xml"
    app:startDestination="@id/initialFragment">

    <fragment
        android:id="@+id/initialFragment"
        android:name="com.example.fragmenttag.InitialFragment"
        android:label="Initial Fragment"
        tools:layout="@layout/initial_fragment">
        <action
            android:id="@+id/action_initialFragment_to_destinationFragment"
            app:destination="@id/destinationFragment" />
    </fragment>
    <fragment
        android:id="@+id/destinationFragment"
        android:name="com.example.fragmenttag.DestinationFragment"
        android:label="Destination Fragment"
        tools:layout="@layout/destination_fragment" />

</navigation>

这是一个 github 存储库,您可以在其中轻松重现错误:https://github.com/dmytroKarataiev/navHostBug

【问题讨论】:

您需要将&lt;fragment 放入FragmentContainerView 【参考方案1】:

no current navigation node 错误发生在没有图表集并且您尝试调用navigate() 时。如果它仅在您使用 FragmentContainerView 并且在配置更改之后发生,那么这将与 this bug 有关,它已修复并计划与 Navigation 2.2.0-rc03 一起发布。

要解决此问题,您可以切换回&lt;fragment&gt; 或删除app:navGraph="@navigation/nav_simple" 并改为调用navController.setGraph(R.navigation.nav_simple)

【讨论】:

我实际上尝试了这种方法,我得到了完全相同的错误。您是否能够查看 repo 并尝试使其与这种方法一起使用? 此外,此崩溃仅在方向更改后发生。它在所有其他时间都有效。 我其实认为这不是同一个错误,导航控制器在我的问题中不为空,但它的后堆栈为空,图表为空。 啊,是的,这是非常重要的信息,听起来你正在经历的是这个other issue。我已经更新了我的答案,以讨论该问题的情况。 这应该在官方codelab的某个地方解释一下!还是我想念它?【参考方案2】:

我没有看到任何解释为什么用 FragmentContainerView 替换 Fragment 视图。这就是为什么添加这个答案:

在 Activity 中托管 Fragment 的常见模式之一是使用 FrameLayout。 Android 社​​区多年来一直在这样做,但现在这种情况将会改变。 androidx 团队引入了这个名为 FragmentContainerView 的新视图来为您完成这项工作。

您所要做的就是将 FrameLayout 替换为 FragmentContainerView,一切都应该开箱即用,您无需在处理片段事务的方式上进行任何更改。

这里获得的好处是改进了对所谓的片段 z 排序的处理。这是他们使用的示例,但基本上这意味着,例如,两个片段之间的退出和进入转换不会相互重叠。相反,这个 FragmentContainerView 将首先启动退出动画,然后是进入动画。

如果你问这个可以替换标签吗?那么答案是肯定的。您所要做的就是在定义 FragmentContainerView 时添加 android:name="your_class_name" ,它将在后台使用 FragmentTransaction 来构建和显示您的片段。这意味着您可以稍后使用片段事务来替换它。

Source

Android Docs

【讨论】:

我不相信这回答了作者提出的问题。 谢谢!在 proguard-rules.pro 中添加规则另请参阅 ***.com/questions/60009473/…。 非常感谢您的回答。这有助于解决我现在面临的问题。它没有解决它。但我更了解FrameLayoutFragmentContainerView 地狱。 关于 android:name="your_class_name" "your_class_name" 应该是什么类?托管活动还是片段? 原来的问题是关于,而不是【参考方案3】:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? 
    return inflater.inflate(R.layout.frag_splash, container, false)

也许您忘记了上面的第三个“false”参数。只有onCreateViewfun这三个参数可以接受。

android developer website

图片来自:https://developer.android.com/reference/androidx/fragment/app/FragmentContainerView

【讨论】:

【参考方案4】:
// drawer layout that I pass is the id of the layout in the activity from which I move to fragment//

SacnFragment sacnFragment = new SacnFragment();
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.drawer_layout, sacnFragment);
    transaction.addToBackStack(null);
    transaction.commit();

【讨论】:

以上是关于<androidx.fragment.app.FragmentContainerView> 与 <fragment> 作为 NavHost 的视图的主要内容,如果未能解决你的问题,请参考以下文章

在迁移到 viewpager2 androidx 时发现此错误“无法解析方法 'super(androidx.fragment.app.FragmentManager)'”

如何用 Android 数据绑定替换 androidx.fragment.app.FragmentContainerView 中的片段

使用 androidx.fragment.app.FragmentContainerView 时出现 ClassNotFoundException

当 minifyEnabled 为 true 时,膨胀类 androidx.fragment.app.FragmentContainerView 时出错

androidx fragment.app FragmentStatePagerAdapter 已弃用(java)

java.lang.ClassCastException: com.example.yijie.MainData cannot be cast to androidx.fragment.app.Fra