Shared ViewModel in Android

14 Feb, 2022
In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities. Almost every application has some communication between various activities or fragments. 
In the article, we are going to learn about Shared ViewModel in Android to communicate with other fragments. We will develop an application containing two fragments in which one fragment updates the data within the ViewModel which is shared between both the fragments and another fragment observes the changes on that data and displays the updated one on the screen. Application’s work is to send->receive->display a message. A sample GIF is given below to get an idea about what we are going to do in this article.
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: Create a class SharedViewModel
Go to the SharedViewModel.kt file and refer to the following code. Below is the code for the SharedViewModel.kt file. Comments are added inside the code to understand the code in more detail.
Kotlin
import androidx.lifecycle.MutableLiveDataimport androidx.lifecycle.ViewModel class SharedViewModel : ViewModel() {     // variable to contain message whenever      // it gets changed/modified(mutable)    val message = MutableLiveData<String>()     // function to send message    fun sendMessage(text: String) {        message.value = text    }}
 
 
Step 3: Create two fragments and they are – MessageSenderFragment & MessageReceiverFragment
 
MessageSenderFragment – To send the message which will be received by MessageReceiverFragment. It will have a Button to send the message after clicking it. Go to the MessageSenderFragment.kt file and refer to the following code. Below is the code for the MessageSenderFragment.kt file. Comments are added inside the code to understand the code in more detail.
 
Kotlin
import android.os.Bundleimport androidx.fragment.app.Fragmentimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.Buttonimport android.widget.EditTextimport androidx.lifecycle.ViewModelProvider class MessageSenderFragment : Fragment() {       // to send message    lateinit var btn: Button         // to write message    lateinit var writeMSg: EditText     override fun onCreateView(        inflater: LayoutInflater,        container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        return inflater.inflate(R.layout.fragment_message_sender, container, false)    }     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)                   // reference for button and EditText        btn = view.findViewById(R.id.button)        writeMSg = view.findViewById(R.id.writeMessage)                   // create object of SharedViewModel        val model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)                   // call function "sendMessage" defined in SharedVieModel          // to store the value in message.        btn.setOnClickListener { model.sendMessage(writeMSg.text.toString()) }    }}
 
 
Navigate to the app > res > fragment_message_sender.xml and add the below code to that file. Below is the code for the fragment_message_sender.xml file.
 
XML
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">     <EditText        android:id="@+id/writeMessage"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:hint="Write your message"        android:textAlignment="center"        app:layout_constraintBottom_toTopOf="@+id/button"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />     <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginBottom="100dp"        android:text="Share Your Message"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
 
 
MessageReceiverFragment – To receive the message sent by MessageSenderFragment. It will have a TextView to show the updated message on the screen. Go to the MessageReceiverFragment.kt file and refer to the following code. Below is the code for the MessageReceiverFragment.kt file. Comments are added inside the code to understand the code in more detail.
 
Kotlin
class MessageReceiverFragment : Fragment() {    // to contain and display shared message    lateinit var displayMsg: TextView    override fun onCreateView(        inflater: LayoutInflater,        container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        // inflate the fragment layout        return inflater.inflate(R.layout.fragment_message_receiver, container, false)    }     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        // reference for the container declared above        displayMsg = view.findViewById(R.id.textViewReceiver)        // create object of SharedViewModel        val model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)        // observing the change in the message declared in SharedViewModel        model.message.observe(viewLifecycleOwner, Observer {            // updating data in displayMsg            displayMsg.text = it        })    }}
 
 
Navigate to the app > res > fragment_message_receiver.xml and add the below code to that file. Below is the code for the fragment_message_receiver.xml file.
 
XML
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">     <TextView        android:id="@+id/textViewReceiver"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="20sp"        android:textColor="@color/black"        android:textAlignment="center"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
 
 
We have created the object of SharedViewModel which is the same object as we are using the same single activity as an owner. This is the reason it is shared. Notice that we have used the requireActivity() in both the fragments.
 
. . .
ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
. . .
 
Step 3: Update the activity_main.xml
 
The activity consists of two fragments and is the host for both the fragments.
 
XML
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">     <fragment        android:id="@+id/receiverFragment"        android:name="com.gfg.article.sharedviewmodel.MessageReceiverFragment"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_marginStart="8dp"        android:layout_marginTop="8dp"        android:layout_marginEnd="8dp"        android:layout_marginBottom="8dp"        app:layout_constraintBottom_toTopOf="@+id/senderFragment"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />     <fragment        android:id="@+id/senderFragment"        android:name="com.gfg.article.sharedviewmodel.MessageSenderFragment"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_marginStart="8dp"        android:layout_marginTop="8dp"        android:layout_marginEnd="8dp"        android:layout_marginBottom="8dp"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/receiverFragment" /> </androidx.constraintlayout.widget.ConstraintLayout>
 
 
MainActivity.kt remains as it is.
 
Kotlin
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundle class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)    }}
 
 
Now, Run the app.
 
Output:
 
 
Source Code: Click Here
 
varshagumber28
Blogathon-2021
Picked
Android
Blogathon
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Difference Between Implicit Intent and Explicit Intent in Android
How to Create and Add Data to SQLite Database in Android?
Android Projects - From Basic to Advanced Level
Retrofit with Kotlin Coroutine in Android
Navigation Drawer in Android
How to Call or Consume External API in Spring Boot?
Re-rendering Components in ReactJS
SQL Query to Insert Multiple Rows
How to Connect Python with SQL Database?
Top 10 Fastest Programming Languages