ViewModel compartido en Android

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í

Publicación traducida automáticamente

Artículo escrito por anju1406 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *