En Android, podemos usar ViewModel para compartir datos entre varios fragmentos o actividades compartiendo el mismo ViewModel entre todos los fragmentos y pueden acceder a todo lo definido en ViewModel. Esta es una forma de tener comunicación entre fragmentos o actividades. Casi todas las aplicaciones tienen alguna comunicación entre varias actividades o fragmentos.
¿Qué vamos a construir en este artículo?
En el artículo, aprenderemos sobre Shared ViewModel en Android para comunicarnos con otros fragmentos. Desarrollaremos una aplicación que contiene dos fragmentos en los que un fragmento actualiza los datos dentro del ViewModel que se comparte entre ambos fragmentos y otro fragmento observa los cambios en esos datos y muestra el actualizado en la pantalla. El trabajo de la aplicación es enviar->recibir->mostrar un mensaje. A continuación se proporciona un GIF de muestra para tener una idea de lo que vamos a hacer en este artículo.
Implementación paso a paso
Paso 1: Crear un nuevo proyecto
Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación.
Paso 2: crea una clase SharedViewModel
Vaya al archivo SharedViewModel.kt y consulte el siguiente código. A continuación se muestra el código para el archivo SharedViewModel.kt. Se agregan comentarios dentro del código para comprender el código con más detalle.
Kotlin
import androidx.lifecycle.MutableLiveData import 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 } }
Paso 3: crea dos fragmentos y son: MessageSenderFragment y MessageReceiverFragment
MessageSenderFragment : para enviar el mensaje que será recibido por MessageReceiverFragment . Tendrá un botón para enviar el mensaje después de hacer clic en él. Vaya al archivo MessageSenderFragment.kt y consulte el siguiente código. A continuación se muestra el código del archivo MessageSenderFragment.kt. Se agregan comentarios dentro del código para comprender el código con más detalle.
Kotlin
import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.EditText import 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()) } } }
Vaya a la aplicación > res > fragment_message_sender.xml y agregue el siguiente código a ese archivo. A continuación se muestra el código para el archivo fragment_message_sender.xml .
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: para recibir el mensaje enviado por MessageSenderFragment. Tendrá un TextView para mostrar el mensaje actualizado en la pantalla. Vaya al archivo MessageReceiverFragment.kt y consulte el siguiente código. A continuación se muestra el código del archivo MessageReceiverFragment.kt. Se agregan comentarios dentro del código para comprender el código con más detalle.
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 }) } }
Vaya a la aplicación > res > fragment_message_receiver.xml y agregue el siguiente código a ese archivo. A continuación se muestra el código para el archivo fragment_message_receiver.xml .
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>
Hemos creado el objeto de SharedViewModel que es el mismo objeto que estamos usando la misma actividad única como propietario. Esta es la razón por la que se comparte . Tenga en cuenta que hemos utilizado requireActivity() en ambos fragmentos.
. . .
ViewModelProvider (requireActivity()).get(SharedViewModel::class.java)
. . .
Paso 3: actualice la actividad_principal.xml
La actividad consta de dos fragmentos y es el anfitrión de ambos fragmentos.
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 permanece como está.
Kotlin
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
Ahora, ejecuta la aplicación.
Producción:
Código fuente: Haga clic aquí