How to Pass Data Between Fragments in Android using Kotlin

How to Pass Data Between Fragments in Android using Kotlin

Passing data from a Fragment to another Fragment it’s not the same as passing data from one Activity to another. You need first to pass the data to Activity and then to the second Fragment.

If you have created your fragments and you just want to know how to pass data from one Fragment to another, skip the following step.

Creating Fragments

In this example, we have a fragment that contains an EditText, where we type a text and a Button that sends the text to the 2nd fragment and shows it in a TextView.

First, let’s go and create the layout of the fragment with the EditText and the Button (fragment_1.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:gravity="center">


    <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical">

        <EditText
                android:id="@+id/input_edittext"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="20dp"
                android:textColor="@android:color/white"
                android:textStyle="bold"
        />

        <Button
                android:id="@+id/enter_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Enter"
                android:textStyle="bold"
                android:textColor="@android:color/white"
                android:padding="10dp"
                android:textAllCaps="false"
                android:background="@color/colorPrimaryDark"
        />
    </LinearLayout>
</RelativeLayout>

Next, let’s do the same for the fragment with the TextView (fragment_2.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimaryDark"
        android:gravity="center">

    <TextView
            android:id="@+id/output_textview"
            android:textColor="@android:color/white"
            android:textStyle="bold"
            android:textSize="22sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
</RelativeLayout>

Go and add an id with a name ‘content_id’ on parent layout in the activity_main.xml file like the image below:

Now, let’s create the Kotlin class for our first fragment (Fragment1.kt) and second fragment (Fragment2.kt) like that:

class Fragment1: Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.fragment_1, container, false)
    
        return rootView
    }
}
class Fragment2: Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.fragment_2, container, false)

        return rootView
    }

}

Passing Data Between Fragments

When we want to pass data between fragments, we are doing it with the help of the Activity which contains these fragments.

In our example, the Activity is the MainActivity.kt.

So we are going to use the MainActivity to pass the data from the first to the second fragment using an interface.

In our example we call it Communicator:

interface Communicator {

    fun passDataCom(editext_input: String)

}

Inside the interface there’s a method passDataCom where we pass the input text from the EditText from our first fragment.

Now, add Communicator at the top of the MainActivity and implement the methods by pressing Alt+Enter(Windows) or Command+Enter(MacOS), then Enter and OK on the new window.

Next, let’s go to Fragment1.kt and initialize our Communicator and call the method with the text from the EditText as a parameter:

class Fragment1: Fragment() {

    lateinit var comm: Communicator

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.fragment_1, container, false)
        comm = activity as Communicator

        rootView.enter_btn.setOnClickListener {
            comm.passDataCom(rootView.input_edittext.text.toString())
        }
        return rootView
    }
}

Now it’s time to go back to our MainActivity and pass the value from Fragment1 to the Fragment2.

To do that, we’re taking the value and we’re adding it to a Bundle.

Then we pass the bundle data as arguments to the Fragment2

And at the end we display the new fragment by replacing the Fragment1 with the Fragment2 in the MainActivity like that:

class MainActivity : AppCompatActivity(), Communicator {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Replace Main Activity content with the Fragment1 content
        val fragment1 = Fragment1()
        supportFragmentManager.beginTransaction().replace(R.id.content_id, fragment1).commit()

    }

    override fun passDataCom(editext_input: String) {
        val bundle = Bundle()
        bundle.putString("input_txt",editext_input)

        val transaction = this.supportFragmentManager.beginTransaction()
        val frag2 = Fragment2()
        frag2.arguments = bundle

        transaction.replace(R.id.content_id, frag2)
        transaction.addToBackStack(null)
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        transaction.commit()
    }
}

In the code above, we gave a key name “input_txt” for our text. This will help us to retrieve the value from our 2nd fragment.

After we have sent the value from the 1st fragment, it’s time to retrieve it from our 2nd fragment and display it on the screen.

Go to our Fragment2 and paste the following code:

class Fragment2: Fragment() {

    var inputText: String? = ""

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.fragment_2, container, false)
        inputText = arguments?.getString("input_txt")

        rootView.output_textview.text = inputText

        return rootView
    }

}

Here we’re getting the value with the key name, we put earlier, and we display it on a TextView.

You can find the final project here

Did you find this tutorial helpful?



If you have any questions, please feel free to leave a comment below

Subscribe
Notify of
guest
23 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Sal

Hi,

Thanks this was very helpful. One question though, what is the following line of code does in the program?

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)

regards,

Sal

Kevin

Hi!

Thank you so much, this was very helpful and by far the best described tutorial within this subject!

Regards
Kevin

Juan Carlos

Hi,

The correct works fine, good explained, thanks!

I try send not 1 but 2 data to fragment2, but only I can see 1 data in the next screen. I do another TextView in diferent position than “output_textview”, and another “rootView.enter_btn.setOnClickListener” an soon in Fragment1.kt.

Any suggest? Thanks!

Caner

Hello, Nice tutorial good work!! I am trying to pass 2 data from “Activity” not from fragment. How can I do that ?

Caner

You say that I dont have to do anything in the article, just your comment ?

Caner

val personInfo = intent.extras!!.get("extra") as UserInfoModel
val email = personInfo.personEmail
val name = personInfo.personName
val bundle = Bundle()
bundle.putString("data1", email)
bundle.putString("data2", name)
val myFragment = ProfileFragment()
myFragment.arguments = bundle
supportFragmentManager.beginTransaction()
.replace(R.id.profileFragment, ProfileFragment).commit()

val myFragment = MyFragment()-> What should I write instead of MyFragment. In my code its my fragment class name. Also R.id.profileFragment, ProfileFragment gives error which is “classifier does not have companion object, and thus must be initialized here”

Caner

Thank you for the answer, i have last one. I am adding fragments in onCreate methot on mainActivity. like that

I wrote the code but It gaves error and returns to splash screen. I wonder why ?

Caner

I make it worked but its breaking fragments. tabbs are not sliding left and right also its only rendering the target activity to screen which is profilefragment.

Caner

Yeah, I know that but I couldn’t figure it out.

Vivek

Thanks for such a nice tutorial.

noor

Hi,
Thank you for the tutorial.
I have problem running the app
 

 2020-06-12 08:33:42.420 8418-8418/name.package E/AndroidRuntime: FATAL EXCEPTION: main
    Process: name.package., PID: 8418
    kotlin.UninitializedPropertyAccessException: lateinit property comm has not been initialized
        at name.package.TourneesListAdapter.getComm(TourneesListAdapter.kt:41)
        at name.package.TourneesListAdapter$onBindViewHolder$$inlined$let$lambda$1.onClick(TourneesListAdapter.kt:57)

And when I insert
 

comm = activity as Communicator

in the onCreate of the first frangment, “activity” is not allowed
 
I don’t have a button but a viewholder
 
can you help me plz?
 

override fun onBindViewHolder(holder: TourneesViewHolder, position: Int) {
    tourneeList?.let {
        val tournee = it[position]
        holder.tourneeText.text = tournee.tourneeNom
        holder.itemView.setOnClickListener {
            Log.d(TAG, "onItemClick for ID: ${tourneeArrayList[position].id}")

            comm.passDataCom(tournee.id)
        }
    }
}

 
 
 
 
 

noor

Thank you again for you help
I can’t manage it to work,
“activity” is not allowed, I don’t know how to adapt “myRecyclerView”
 
here the code of the sender fragment found on github and trying to adapt it:

class TourneesListAdapter(val context: Context) : RecyclerView.Adapter<TourneesViewHolder>() {
 
   private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
   private var tourneeList: List<Tournee>? = null
 
   fun setTourneeList(tourneeList: List<Tournee>) {
       this.tourneeList = tourneeList
       notifyDataSetChanged()
   }
 
   lateinit var comm: Communicator
 
   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TourneesViewHolder {
       val itemView = layoutInflater.inflate(R.layout.item_list_tournee, parent, false)
       comm = activity as Communicator
       return TourneesViewHolder(itemView)
   }
 
   override fun onBindViewHolder(holder: TourneesViewHolder, position: Int) {
       tourneeList?.let {
           val tournee = it[position]
           holder.tourneeText.text = tournee.tourneeNom
           holder.itemView.setOnClickListener {
               Log.d(TAG, " onItemClick for ID: ${tournee.id} ")
 
               comm.passDataCom(tournee.id)
           }
       }
   }
 
   override fun getItemCount(): Int {
       return if (tourneeList == null) {
           0
       } else {
           tourneeList!!.size
       }
   }
 
   class TourneesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
       val tourneeText: TextView = itemView.findViewById(R.id.tvTournee)
   }
 
}

 
 

noor

Thank you again 🙂
It work now after some modification