I'm using a navigation graph to navigate between fragments. Everything works fine, but I wonder how to pass argument name in an elegant way.
Here is my code snippet from navSheet.xml
:
A source fragment action:
<action
android:id="@+id/action_go_to_B"
app:destination="@id/id_fragment_b">
<argument
android:name="@string/fragment_b_arg_key_name"
app:argType="integer"/>
</action>
A destination fragment:
<fragment
android:id="@+id/id_fragment_b"
android:name="pl.asd.FragmentB"
tools:layout="@layout/fragment_b">
<argument
android:name="@string/fragment_b_arg_key_name"
app:argType="integer"/>
</fragment>
I store my argument key in string.xml
:
<string name="fragment_b_arg_key_name" translatable="false">arg_fragment_b</string>
And at the end I try to get my argument in destination fragment:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
selectedId = it.getInt(getString(R.string.fragment_b_arg_key_name))
}
}
The problem is with android:name="@string/fragment_b_arg_key_name"
.
I've seen on the debugger that there is an incorrect bundle key. It should be like:
Bundle[{arg_fragment_b=-730732511}]
but I get:
Bundle[{@string/fragment_b_arg_key_name=-730732511}]
Two questions:
What's wrong with using a @string/fragment_b_arg_key_name
in navSheet.xml so it not returns the content of @string/fragment_b_arg_key_name
but raw reference.
How to not hard-code arguments name that I use in Fragments, navSheet.xml
and other classes? How to store such keys in one place?
What's wrong with using a @string/fragment_b_arg_key_name in navSheet.xml so it not returns the content of @string/fragment_b_arg_key_name but raw reference.
Simply because Android Navigation component does not support that feature to parse the string. Every string put in android:name will become the raw id for the bundle. You can issue this in https://issuetracker.google.com/issues
However, there is better solution for this. See below.
How to not hard-code arguments name that I use in Fragments, navSheet.xml and other classes? How to store such keys in one place?
Use safe args https://developer.android.com/jetpack/androidx/releases/navigation#safe_args
You can change your codes like below
FragmentA
findNavController().navigate(R.id.id_fragment_b, FragmentBArgs(id).toBundle())
FragmentB
private val args : FragmentBArgs by navArgs()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
selectedId = args.arg_fragment_b
}
in navSheet.xml:
<argument
android:name="arg_fragment_b"
app:argType="integer"/>
So, no need to store the keys, because safeargs will generate the arguments for you, and by default it is non-nullable.
To put the argument as Nullable, use app:nullable="true"