I cannot set Safe Args default value

2.1k Views Asked by At

I have a String type arg send from NewCodeFragment to MainFragment.

If I set a default value, then I got a 'too many args' error.

How can I set a default value? My understanding is if I send a arg, then the destination fragment will receive the arg, else it will receive the default value. Wrong?

Problem code:

navigation XML:

<argument
    android:name="aArg"
    app:argType="string"
    app:nullable="true"
    android:defaultValue="@null" />

fragment.class :

val aArg="abc"      
// build error, it says too many args    
this.findNavController().navigate(NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment(aArg))

No problem code:

navigation XML:

<argument
    android:name="aArg"
    app:argType="string"
    app:nullable="true"/>     // remove android:defaultValue="@null"

fragment.class :

val aArg="abc"      
this.findNavController().navigate(NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment(aArg))

Another no problem code:

navigation XML:

<argument
    android:name="aArg"
    app:argType="string"
    app:nullable="true"
    android:defaultValue="@null" />

fragment.class :

val aArg="abc"      
this.findNavController().navigate(NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment())   // remove aArg
3

There are 3 best solutions below

7
On

I like the last approach. Here argument can have default value. If you have a standard value instead of passing it in the argument my suggestion would be you keep it in the destination fragment that will receive the arguments. So, you won't have to add the same default string everywhere. If the defaultValue from args is null, you can use the value on that fragment.

<argument
    android:name="aArg"
    app:argType="string"
    app:nullable="true"
    android:defaultValue="@null" />

For example, 3 Fragments A, B and C are going Fragment X with args. A passes "abc", B and C pass null. Now you can have the condition in Fragment X when reading from the args,

val aArgument = safeArgs.aArg?.let {
    // Use it
    it
} else {
    // Use the default String
    "This is your default string"
}
0
On

If your fragment parameter has a default value the generated builder method will not have parameter for it. You will need to set the value of that fragment parameter separately on the xDirections object. There should be a method to set each parameter. For your example to work you will need to do something like if using Java:

String aArg = "abc";
NewCodeFragmentDirections.ActionNewCodeFragmentToMainFragment direction = 
    NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment().aArg(aArg);
this.findNavController().navigate(direction)

In Kotlin this may look something like:

this.findNavController().navigate(
    NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment().apply {
        aArg = "abc"
})
0
On

There must be generated method for setting value. As on authors example must be like this:

val aArg="abc"
val action = NewCodeFragmentDirections.actionNewCodeFragmentToMainFragment.setAArg(aArg)
findNavController().navigate(action)