2

I am uisng Android Jetpack Navigation framework with native java. The thing is the compiler automatically generates the class responsible for the actions defined in the navigation graph, with the correspondent argument setters and getters, but it is not generating a constructor with arguments, but just an empty static constructor.

Is there any way to make the safeArgs plugin or the Navigation framework create this constructors with arguments?

my 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/edicion_basica_navigation"
    app:startDestination="@id/nav_A_fragment">

<fragment
    android:id="@+id/nav_A_fragment"
    android:name="com.fragments.A"
    android:label="@string/A"
    tools:layout="@layout/fragment_a">
    <argument
        android:name="@string/arg_id"
        android:defaultValue="0"
        app:argType="integer" />
    <argument
        android:name="@string/arg_rowid"
        android:defaultValue="0"
        app:argType="integer" />
</fragment>


<fragment
    android:id="@+id/nav_B_fragment"
    android:name="com.fragments.B"
    android:label="@string/b"
    tools:layout="@layout/fragment_b">
    <argument
        android:name="@string/arg_id"
        android:defaultValue="0"
        app:argType="integer" />
    <argument
        android:name="@string/arg_rowid"
        android:defaultValue="0"
        app:argType="integer" />    

</fragment>

<action
    android:id="@+id/A_to_B"
    app:destination="@id/nav_B_fragment" />

</navigation>

Thank you

mantc_sdr
  • 451
  • 3
  • 17

2 Answers2

1

It seems the presence of a default value for the argument suppresses the generation of a constructor with arguments.

Here are the experiements I did. If you want to follow along, grab the code from here: https://github.com/google-developer-training/android-kotlin-fundamentals-starter-apps/tree/master/GuessTheWord-Starter (For the benefit of future readers, as of writing this, the last commit to the code was Sep 1, 2020). (You'll have to go up one level to clone or download the GuessTheWord-Starter project (in addition to a bunch of others). Make two copies, GuessTheWordA and GuessTheWordB, for two experiments. Using Android Studio 4.1.2, I had to make the following change in order to get the project to compile. In GuessTheWordA/app/build.gradle, I added the buildToolsVersion line:

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"
    ...

If you view navigation/main_navigation.xml, you'll see that the score fragment contains an argument with a default value. There's an action from the game fragment to the score fragment.

Experiment A

Build > Rebuild Project

By default, if we look at the generated GameFragmentDirections enter image description here

you find the following code: enter image description here

No arguments in the constructor!

Open navigation/main_navigation.xml, select the score fragment and remove the default value of the argument.

Before: enter image description here

After: enter image description here

Build > Rebuild Project

enter image description here

The ActionGameToScore() now has a 'score' argument.

Experiment B

According to the docs (https://developer.android.com/guide/navigation/navigation-pass-data#override_a_destination_argument_in_an_action), we can override a destination argument in an action. So in GuessTheWordB, go to navigation/main_navigation.xml and add the <argument> tag to the 'action_game_to_score' <action>: enter image description here

Build > Rebuild Project

Again, the constructor with arguments gets generated. (Note, in spite of what the documentation shows, if I included the default value in the <argument> within <action> then the constructor doesn't include the arguments.)

Cecil
  • 68
  • 4
0

Could you share the XML for the target fragment you want to go to? You need to define those arguments on the destination fragment itself. like so:

 <fragment android:id="@+id/myFragment" >
     <argument
         android:name="myArg"
         app:argType="integer"
         android:defaultValue="0" />
 </fragment>

Also, don't forget to build afterwards, so that the classes are generated.

Khodor
  • 129
  • 1
  • 7
  • XML uploaded above – mantc_sdr Jan 17 '20 at 12:08
  • I'm sorry I can't test this out for myself right now. Please try putting the action A_to_B inside nav_A_fragment alongside its arguments, build, then call NavAFragmentDirections.AToB(420, 42) for instance. – Khodor Jan 17 '20 at 12:56
  • To clarify, this would actually create your NavDirection object. You should then call something like findNavController.navigate(aToB) – Khodor Jan 17 '20 at 13:07