Search code examples
androidandroid-fragmentsandroid-architecture-navigation

Android NavController: How to open same fragment with same action


I have Category fragment and SubCategoryFragment for entering category children to view. I have action in navigation graph xml to open SubCategoryFragment. If I open any root category and click to any its children then If clicked child catalog has children then I should open SubCategoryFragment with when user clicked it child. There are scheme like a tree:

Root category fragment:

enter image description here

Child category fragment:

enter image description here

Next child category fragment:

enter image description here

When I click last secondary sub child category fragment where same fragment(same action) with previous parent fragment i get following error:

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)

Here navigation 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>

Anybody know how to use same fragment but new multiple instances times with NavController?


Solution

  • It may help to post your navigation graph, but I think you can solve this in one of two ways:

    (1) a local action available to the category fragment, or (2) a global action available to the entire graph.

    <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>
    

    In both cases, a new instance of the fragment should be created.