Open In App

How to Pass Data to Destination using Safe Args in Android?

Improve
Improve
Like Article
Like
Save
Share
Report

SafeArgs is a gradle plugin that allows you to Pass data to destination UI components. It generates simple object and builder classes for type-safe navigation and access to any associated arguments. Safe Args is strongly recommended for navigating and passing data because it ensures type-safety. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Kotlin language. 

Step by Step Implementation

Step 1: Create a new project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.

Step 2: Add dependency

Inside build.gradle (project) add the following code under dependencies.

 dependencies {

    classpath “androidx.navigation:navigation-safe-args-gradle-plugin:2.3.2”

}

Inside build.gradle (app) add the following code and click Sync now

plugins {

   id ‘com.android.application’

   id ‘kotlin-android’

   id ‘kotlin-android-extensions’

   id “androidx.navigation.safeargs.kotlin”

}

Step 3: Create two new Fragments

In this article, we are going to send data from one fragment and receive it in another. So, First, create two Fragments. To create a new Fragment:

Project Name (right click) -> new -> Fragment -> Fragment (Blank)

A dialog box will open. In the Fragment Name write Registration and in fragment layout name write fragment_registration. In a similar way create another fragment with fragment name Detail and fragment layout name as fragment_detail.

Step 4: Create an XML layout of both fragments

Go to the Fragment_registration.xml file and refer to the following code. Below is the code for the Fragment_registration.xml file. This is for the basic layout used in the app.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Registration">
 
    <EditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentEnd="true"
        android:layout_margin="20dp"
        android:ems="10"
        android:hint="Name"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <EditText
        android:id="@+id/et_email"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email"
        android:layout_margin="20dp"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_name" />
 
    <EditText
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Password"
        android:layout_margin="20dp"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_email" />
 
    <Button
        android:id="@+id/button_send"
        android:layout_width="276dp"
        android:layout_height="50dp"
        android:text="Send"
        android:layout_margin="20dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_password" />
   
</androidx.constraintlayout.widget.ConstraintLayout>


Go to the Fragment_detail.xml file and refer to the following code. Below is the code for the Fragment_detail.xml file. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Details">
 
 <TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Name :"
     android:id="@+id/tv1"
     android:textSize="20sp"
     app:layout_constraintLeft_toLeftOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     android:layout_marginTop="50dp"
     android:layout_marginStart="30dp"
     />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:id="@+id/tv_name"
        app:layout_constraintLeft_toRightOf="@id/tv1"
        app:layout_constraintTop_toTopOf="@id/tv1"
        android:layout_marginStart="20dp"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Email :"
        android:id="@+id/tv2"
        android:textSize="20sp"
        app:layout_constraintTop_toBottomOf="@id/tv1"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginTop="20dp"
        android:layout_marginStart="30dp"
        />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:id="@+id/tv_email"
        app:layout_constraintLeft_toRightOf="@id/tv2"
        app:layout_constraintTop_toTopOf="@id/tv2"
        android:layout_marginStart="20dp"
        />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Password :"
        android:id="@+id/tv3"
        android:textSize="20sp"
        app:layout_constraintTop_toBottomOf="@id/tv2"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginTop="20dp"
        android:layout_marginStart="30dp"
        />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:id="@+id/tv_password"
        app:layout_constraintLeft_toRightOf="@id/tv3"
        app:layout_constraintTop_toTopOf="@id/tv3"
        android:layout_marginStart="20dp"
        />
 
</androidx.constraintlayout.widget.ConstraintLayout>


Step 5: Create a new Kotlin class 

Create a new Class User.kt we will use data of custom generic “User” having a name, email, password to pass to another fragment.

Kotlin




import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
 
@Parcelize
data class User(
    val name : String ="",
    val email : String= "",
    val password : String =""
 
) : Parcelable


Step 6: Create a new Navigation graph

res (right click) -> new -> Android resource file 

In the dialog write file name as nav_graph and choose Resource type as “Navigation“. and click Ok. Now open the just created nav_graph.xml file click on the new destination icon and choose both of the fragments. Make Fragment_registration as the home. Create action from fragment_registration to fragment_detail and pass the User argument in the arguments of Fragment_detail. Its XML code is given below.

XML




<?xml version="1.0" encoding="utf-8"?>
<navigation
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/registration">
 
    <fragment
        android:id="@+id/registration"
        android:name="com.geeksforgeeks.navargsexample.Registration"
        android:label="fragment_registration"
        tools:layout="@layout/fragment_registration" >
        <action
            android:id="@+id/action_registration_to_details"
            app:destination="@id/details" />
    </fragment>
 
    <fragment
        android:id="@+id/details"
        android:name="com.geeksforgeeks.navargsexample.Details"
        android:label="fragment_details"
        tools:layout="@layout/fragment_details" >
        <argument
            android:name="user"
            app:argType="com.geeksforgeeks.navargsexample.User" />
    </fragment>
 
</navigation>


Step 7: Working with the activity_main.xml file

Go to the activity_main.xml file and refer to the following code. Below is the code for the activity_main.xml file. This layout contains one Frame Layout and a fragment that will act as a host for the fragments that we created earlier. Notice the navGraph tag inside the fragment tag.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <FrameLayout
        android:id="@+id/frameLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
       
        <!--this fragmnet will act as the host for
            both fragments in the main activity-->
        <fragment
            android:id="@+id/nav_Host_Fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"
            />
 
    </FrameLayout>
 
</androidx.constraintlayout.widget.ConstraintLayout>


Step 8: Working with Registration.kt file

Go to the Registration.kt file and refer to the following code. Below is the code for the Registration.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.geeksforgeeks.navargsexample.databinding.FragmentRegistrationBinding
 
class Registration : Fragment() {
 
    private var _binding: FragmentRegistrationBinding? = null
    private val binding get() = _binding!!
 
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentRegistrationBinding.inflate(inflater, container, false)
        val view = binding.root
 
        // call onClick on the SendButton
        binding.buttonSend.setOnClickListener {
            val name = binding.etName.text.toString()
            val email = binding.etEmail.text.toString()
            val password = binding.etPassword.text.toString()
             
            // create user object and pass the
              // required arguments
            // that is name, email,and password
            val user = User(name,email, password)
             
            // create an action and pass the required user object to it
            // If you can not find the RegistrationDirection try to "Build project"
            val action = RegistrationDirections.actionRegistrationToDetails(user)
             
            // this will navigate the current fragment i.e
              // Registration to the Detail fragment
            findNavController().navigate(
                action
            )
        }
        return view
    }
 
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}


Step 9: Working with the Details.kt file

Go to the Details.kt file and refer to the following code. Below is the code for the Details.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.navArgs
import com.geeksforgeeks.navargsexample.databinding.FragmentDetailsBinding
 
class Details : Fragment() {
 
    private var _binding: FragmentDetailsBinding? = null
    private val binding get() = _binding!!
 
    // get the arguments from the Registration fragment
    private val args : DetailsArgs by navArgs()
 
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentDetailsBinding.inflate(inflater, container, false)
        val view = binding.root
 
        // Receive the arguments in a variable
        val userDetails = args.user
       
        // set the values to respective textViews
        binding.tvName.text = userDetails.name
        binding.tvEmail.text = userDetails.email
        binding.tvPassword.text = userDetails.password
 
        return view
    }
 
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}


Note: In this example, we don’t have to write any code inside ActivityMain.kt

Output:

Github Repo here.



Last Updated : 30 Jun, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads