Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass safe-args when navigate to fragment

It's quite easy to pass safe-args when using navigation through an action (with directions class). But how to pass safe-args in case of using navigation to fragment directly?

navController?.navigate(R.id.detailFragment)

nav_graph:

<fragment
    android:id="@+id/detailFragment"
    android:name="com.example.ui.main.detail.DetailFragment"
    android:label=" "
    tools:layout="@layout/detail_fragment" >
    <argument
        android:name="templateCode"
        app:argType="string" />
    <action
        android:id="@+id/action_start_guide"
        app:destination="@id/fillInfoFragment" />
</fragment>
like image 507
Francis Avatar asked Oct 03 '18 08:10

Francis


People also ask

What does the safe args gradle plugin do select all that apply?

What does the Safe Args Gradle plugin do? Select all that apply. Choose as many answers as you see fit. Generates simple object and builder classes for type-safe access to arguments specified for destinations and actions.

Is there any dependency that needs to get added before using safe args?

SafeArgs is not the same kind of library module as the other parts of navigation; it's not an API per se, but rather a gradle plugin that will generate code. So I needed to pull it in as a gradle dependency and then apply the plugin to run at build time, to generate the necessary code.


Video Answer


2 Answers

It's a good idea to use type-safe way because it take you compile time safety and some convenience.

This library will build argument's class MyDestinationArgs. You can use it to build Bundle and pass result to destination this way:

val args = DetailFragmentArgs.Builder("template_code").build().toBundle()
navController?.navigate(R.id.confirmationAction, args) 

On receiver side, you can retrieve data also using arguments class:

val templateCode = SecondFragmentArgs.fromBundle(arguments).templateCode

If we can't use safeargs library by some reasons,

we can pass data also inside Bundle. Suppose you have added

const val ARG_TEMPLATE_CODE = "templateCode"

constant in companion object of DetailFragment (static final field in Java)

Now you can pass data this way:

val args = Bundle()
args.putString(DetailFragment.ARG_TEMPLATE_CODE, "some_code")
navController?.navigate(R.id.confirmationAction, args)

And receiver fragment can obtain data from arguments:

arguments?.getString(ARG_TEMPLATE_CODE)

Or, if target destination is Activity, you can get data from intent extras (ARG_TEMPLATE_CODE constant now from destination activity):

intent?.extras?.getString(ARG_TEMPLATE_CODE)
  

Read more in documentation here and here.

like image 104
Sergey Bubenshchikov Avatar answered Oct 11 '22 14:10

Sergey Bubenshchikov


The safe way is to define global action in case of need to navigate to fragment "directly"

<fragment
    android:id="@+id/detailFragment"
    android:name="com.example.ui.main.detail.DetailFragment"
    android:label=" "
    tools:layout="@layout/detail_fragment" >
    <argument
        android:name="templateCode"
        app:argType="string" />
    <action
        android:id="@+id/action_start_guide"
        app:destination="@id/fillInfoFragment" />
</fragment>

<action
    android:id="@+id/action_detail_fragment"
    app:destination="@id/fillInfoFragment" />

then

findNavController().navigate(NavGraphDirection.actionDetailFragment(templateCode))
like image 29
Francis Avatar answered Oct 11 '22 16:10

Francis