2

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
caibirdcnb
  • 275
  • 5
  • 18

3 Answers3

3

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

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"
}
Mohit Ajwani
  • 1,328
  • 12
  • 24
  • My problem is with default value, I cannot pass "abc" anymore, it got a 'too many args' error as case 1 in my topic. – caibirdcnb May 06 '21 at 09:40
  • In my case 3, you see I have to remove aArg to eliminate the building error, in that case, how can I pass aArg to destination? I would always pass default value forever. – caibirdcnb May 06 '21 at 09:41
  • @caibirdcnb - Did you try rebuilding the project after changing the arguments? Because navigations arguments need project rebuild after changing, else it takes the previously generated code. – Mohit Ajwani May 06 '21 at 10:04
  • @caibirdcnb Use approach 1 and rebuild project. That should solve the problem. – Mohit Ajwani May 06 '21 at 10:09
  • I did tried rebuild, I've also tried invalidate caches /restart, but no lucky. – caibirdcnb May 06 '21 at 10:25
  • I have the same code and it works. I hope you added arguments to all the navigation actions where you are going to NewCodeFragment. – Mohit Ajwani May 06 '21 at 10:36
  • This might help https://issuetracker.google.com/issues/188855904 – Gulzar Bhat Jun 20 '23 at 16:53
0

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)