Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with Navigation Component Duplicate NavArgs

I have a fragment:

class SomeFragment {
    private val args by navArgs<SomeFragmentArgs>()
}

this fragment is used in two navigation graph:

first_nav.xml

....
<fragment
    android:id="@+id/initialFragment"
    android:name="com.example.InitialFragment"
    android:label="Initial Fragment">
    <action
        android:id="@+id/action_to_some_fragment"
        app:destination="@id/someFragment" />
</fragment>
<fragment
    android:id="@+id/someFragment"
    android:name="com.example.SomeFragment"
    android:label="Some Label">
    <argument
        android:name="someType"
        app:argType="com.example.someType"/>
</fragment>
....

second_nav.xml

....
<fragment
    android:id="@+id/initialFragment2"
    android:name="com.example.InitialFragment2"
    android:label="Initial Fragment">
    <action
        android:id="@+id/action_to_some_fragment"
        app:destination="@id/someFragment" />
</fragment>
<fragment
    android:id="@+id/someFragment"
    android:name="com.example.SomeFragment"
    android:label="Some Label">
    <argument
        android:name="someType"
        app:argType="com.example.someType"/>
</fragment>
....

But when I build the project for release R8 throws:

R8: Program type already present: com.example.SomeFragmentArgs$Companion

Can anyone help me on this?

like image 629
Archie G. Quiñones Avatar asked Nov 22 '19 06:11

Archie G. Quiñones


1 Answers

I am facing this issue too. We are using multiple modular developing and the direction class are generated in different modules. So that there are several FragmentDirections in everywhere and cause R8 Program type already present since they all got companion object.

There are two solutions/workarounds.

  1. Isolate this fragment into an independent navigation.xml

In your case you can write a some_fragment_nav.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"
app:startDestination="@id/someFragment"
android:id="@+id/some_fragment_nav">

<fragment
    android:id="@+id/someFragment"
    android:name="com.example.SomeFragment"
    android:label="lable">

    <action
        android:id="@+id/what_ever_action_you_want"
        app:destination="@id/share_this_id_to_ids" />


    <argument
        android:name="someType"
        app:argType="com.example.someType"/>

</fragment>

</navigation>

and use

<include app:graph="@navigation/some_fragment_nav"/>

in both of your navigation graphs. That will work. If you are using multi-modular developing. You need to share action id by writing your id into ids.xml.

  1. Copy and past SomeFragment to different naming like SomeFragment1.kt SomeFragment2.kt. And there won't be any R8 Program type already present too. Further more you can make SomeFragment as open class and SomeFragment1 extend SomeFragment with empty implementation.

My personal prospects.. 2 is better than 1 since they all look like workarounds to me. Until jetbrains change the rules of generated FragmentDirection class.

like image 191
Shu Zhang Avatar answered Nov 06 '22 01:11

Shu Zhang