8

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:

  1. 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.

  2. 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?

1 Answer 1

10

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"

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.