Android NavController:如何用相同的动作打开相同的片段

Posted

技术标签:

【中文标题】Android NavController:如何用相同的动作打开相同的片段【英文标题】:Android NavController: How to open same fragment with same action 【发布时间】:2020-02-19 17:10:54 【问题描述】:

我有 Category 片段和 SubCategoryFragment 用于输入要查看的类别子项。我在导航图 xml 中有打开 SubCategoryFragment 的操作。如果我打开任何根类别并单击其任何子目录,那么如果单击的子目录有子目录,那么我应该在用户单击子目录时打开 SubCategoryFragment。有像树一样的方案:

根类别片段:

子类别片段:

下一个子类别片段:

当我单击与前一个父片段相同的片段(相同操作)的最后一个二级子子类别片段时,我收到以下错误:

2019-10-23 16:48:03.472 24670-24670/com.example.store E/androidRuntime: FATAL EXCEPTION: main
Process: com.example.store, PID: 24670
java.lang.IllegalArgumentException: navigation destination com.example.store:id/action_catalogPage_to_subCatsPage is unknown to this NavController
    at androidx.navigation.NavController.navigate(NavController.java:789)
    at com.example.store.helpers.NavigationExtensionsKt.navigateSafe(NavigationExtensions.kt:271)
    at com.example.store.helpers.NavigationExtensionsKt.navigateSafe$default(NavigationExtensions.kt:266)
    at com.example.store.fragments.catalog.SubCatsPage.onItemClick(SubCatsPage.kt:78)
    at com.example.store.helpers.adapters.catalog.SubCatsAdapter$SubCatsItemHolder$bindTo$1.onClick(SubCatsAdapter.kt:75)
    at android.view.View.performClick(View.java:7125)
    at android.view.View.performClickInternal(View.java:7102)
    at android.view.View.access$3500(View.java:801)
    at android.view.View$PerformClick.run(View.java:27336)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

这里导航xml:

<?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/catalog"
    app:startDestination="@id/catalogPage">

    <fragment
        android:id="@+id/catalogPage"
        android:name="com.example.store.fragments.catalog.CatalogPage"
        android:label="fragment_catalog_page"
        tools:layout="@layout/fragment_catalog_page" >
        <action
            android:id="@+id/action_catalogPage_to_subCatsPage"
            app:destination="@id/catalogSubCatsPage" />
        <action
            android:id="@+id/action_catalogPage_to_catalogShowCatProductsPage"
            app:destination="@id/catalogShowCatProductsPage" />
    </fragment>

    <dialog
        android:id="@+id/productDetailSheet"
        android:name="com.example.store.fragments.products.ShowProductDetailsBottomSheet"
        tools:layout="@layout/fragment_dialog_pr_detail_secondary">

        <argument
            android:name="productId"
            app:argType="string"
            android:defaultValue='"0"' />
        <deepLink
            android:id="@+id/deepLink4"
            app:uri="https://com.example/p/productId"
            android:autoVerify="true" />
    </dialog>

    <fragment
        android:id="@+id/catalogSubCatsPage"
        android:name="com.example.store.fragments.catalog.SubCatsPage"
        android:label="SubCatsPage" />

    <fragment
        android:id="@+id/catalogShowCatProductsPage"
        android:name="com.example.store.fragments.products.ShowCatProductsPage"
        android:label="fragment_show_cat_products_page"
        tools:layout="@layout/fragment_show_cat_products_page" />
</navigation>

有人知道如何使用 NavController 使用相同的片段但新的多个实例时间吗?

【问题讨论】:

你能添加你的navigation.xml文件吗 【参考方案1】:

发布您的导航图可能会有所帮助,但我认为您可以通过以下两种方式之一解决此问题:

(1) 类别片段可用的本地操作,或 (2) 对整个图可用的全局操作。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/category">

    <fragment
        android:id="@+id/category"
        android:name="com.example.app.CategoryFragment">

        <argument
            android:name="categoryId"
            app:argType="string"/>

        <!-- (1) Local action to self (category fragment) -->
        <action
            android:id="@+id/open_category"
            app:destination="@id/category"/>

    </fragment>

    <!-- (2) Global action to category fragment-->
    <action
        android:id="@+id/open_category_global"
        app:destination="@id/category"/>

</navigation>

在这两种情况下,都应该创建片段的新实例。

【讨论】:

我使用这个解决方案,但不适合我!不要创建新片段!【参考方案2】:

您刚刚将目标 ID 设置为与片段 ID 相同。

如下图

<fragment
        android:id="@+id/externalProfileFragment"
        android:name="com.social.footprint.ui.external_user_profile.ExternalProfileFragment"
        android:label="ExternalProfileFragment"
        tools:layout="@layout/external_profile_fragment">
        <argument
            android:name="user_id"
            app:argType="string" />
        <action
            android:id="@+id/action_externalProfileFragment_to_externalProfileFragment"
            app:destination="@id/externalProfileFragment" />


</fragment>

【讨论】:

以上是关于Android NavController:如何用相同的动作打开相同的片段的主要内容,如果未能解决你的问题,请参考以下文章

Android 在使用 NavController 时向上导航正确的图表

Android:使用 BottomNavigationView、NavController 和 SafeArgs 恢复片段

当我在 LiveData 观察者中使用 navController 时,Android Navigation 组件图停止正常工作

Android开发 报错: xxx does not have a NavController set on xxx

如何用android studio 查看jar包源码

如何用android studio 编成app