Patrón de arquitectura MVVM (Model View ViewModel) en Android

Los desarrolladores siempre prefieren un código limpio y estructurado para los proyectos. Al organizar los códigos de acuerdo con un patrón de diseño, ayuda en el mantenimiento del software. Al tener conocimiento de todas las partes lógicas cruciales de la aplicación de Android , es más fácil agregar y eliminar funciones de la aplicación. Además, los patrones de diseño también aseguran que todos los códigos se cubran en las pruebas unitarias sin la interferencia de otras clases. Model — View — ViewModel (MVVM) es el patrón de arquitectura de software reconocido en la industria que supera todos los inconvenientes de los patrones de diseño MVP y MVC . MVVM sugiere separar la lógica de presentación de datos (vistas o interfaz de usuario) de la parte lógica empresarial central de la aplicación. 

Las capas de código separadas de MVVM son:

  • Modelo: esta capa es responsable de la abstracción de las fuentes de datos. Model y ViewModel trabajan juntos para obtener y guardar los datos.
  • Vista: El propósito de esta capa es informar al ViewModel sobre la acción del usuario. Esta capa observa el ViewModel y no contiene ningún tipo de lógica de aplicación.
  • ViewModel: Expone esos flujos de datos que son relevantes para la Vista. Además, sirve como enlace entre el Modelo y la Vista.

MVVM (Model View ViewModel) Architecture Pattern in Android

El patrón MVVM tiene algunas similitudes con el patrón de diseño MVP (Modelo – Vista – Presentador) ya que ViewModel desempeña el rol de Presentador. Sin embargo, los inconvenientes del patrón MVP han sido resueltos por MVVM de las siguientes maneras:

  1. ViewModel no contiene ningún tipo de referencia a la Vista.
  2. Existe una relación de muchos a 1 entre View y ViewModel.
  3. No hay métodos de activación para actualizar la Vista.

Formas de implementar MVVM en el proyecto

Hay 2 formas de implementar el patrón de diseño MVVM en proyectos de Android:

  1. Uso de la biblioteca DataBinding lanzada por Google
  2. Usando cualquier herramienta como RxJava para DataBinding.

El enlace de datos:

Google lanza la biblioteca de vinculación de datos para Android que permite a los desarrolladores vincular los componentes de la interfaz de usuario en los diseños XML con los repositorios de datos de la aplicación. Esto ayuda a minimizar el código de la lógica de la aplicación central que se vincula con View. Además, el enlace de datos bidireccional se realiza para vincular los objetos a los diseños XML para que tanto el objeto como el diseño puedan enviarse datos entre sí. Este punto se puede visualizar con el ejemplo de este tutorial.

La sintaxis para el enlace de datos bidireccional es @={variable}

Ejemplo de patrón de arquitectura MVVM

Aquí hay un ejemplo de una aplicación de Android de inicio de sesión de usuario de actividad única para mostrar la implementación del patrón de arquitectura MVVM en proyectos. La aplicación le pedirá al usuario que ingrese el ID de correo electrónico y la contraseña. En función de las entradas recibidas, ViewModel notifica a View qué mostrar como un mensaje de brindis . ViewModel no tendrá una referencia a View

Para habilitar DataBinding en la aplicación de Android, se deben agregar los siguientes códigos en el archivo build.gradle(build.gradle (:app)) de la aplicación:

Habilitar enlace de datos:

android {

   el enlace de datos {

       habilitado = verdadero

      }

}

Agregar dependencia del ciclo de vida:

implementación ‘android.arch.lifecycle:extensiones:1.1.1’

A continuación se muestra la implementación completa paso a paso de la aplicación de Android User-Login con el patrón MVVM.

Implementación paso a paso

Nota: Los siguientes pasos se realizan en Android Studio versión 4.0

Paso 1: Crear un nuevo proyecto

  • Haga clic en Archivo, luego en Nuevo => Nuevo proyecto.
  • Elija Actividad vacía
  • Seleccionar idioma como Java/Kotlin
  • Seleccione el SDK mínimo según su necesidad.

Paso 2: modificar el archivo String.xml

Todas las strings que se utilizan en la actividad se enumeran en este archivo.

XML

<resources>
    <string name="app_name">GfG | MVVM Architecture</string>
    <string name="heading">MVVM Architecture Pattern</string>
    <string name="email_hint">Enter your Email ID</string>
    <string name="password_hint">Enter your password</string>
    <string name="button_text">Login</string>
</resources>

Paso 3: Creando la clase Modelo

Cree una nueva clase llamada Modelo en la que se incluirá el ID de correo electrónico y la contraseña ingresados ​​por el usuario. A continuación se muestra el código para implementar la clase Model adecuada.

Java

import androidx.annotation.Nullable;
 
public class Model {
 
    @Nullable
    String email,password;
 
    // constructor to initialize
    // the variables
    public Model(String email, String password){
        this.email = email;
        this.password = password;
    }
 
    // getter and setter methods
    // for email variable
    @Nullable
    public String getEmail() {
        return email;
    }
 
    public void setEmail(@Nullable String email) {
        this.email = email;
    }
 
    // getter and setter methods
    // for password variable
    @Nullable
    public String getPassword() {
        return password;
    }
 
    public void setPassword(@Nullable String password) {
        this.password = password;
    }
 
}

Paso 4: trabajar con el archivo activity_main.xml

Abra el archivo activity_main.xml y agregue 2 EditText para obtener entradas para el correo electrónico y la contraseña. También se requiere un botón de inicio de sesión para validar la entrada del usuario y mostrar el mensaje Toast apropiado. A continuación se muestra el código para diseñar un diseño de actividad adecuado.

Nota: Para el correcto funcionamiento de la biblioteca de vinculación de datos, es necesario configurar la etiqueta de diseño en la parte superior. La etiqueta de diseño de restricción de XML no funcionará en este caso.

XML

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:bind="http://schemas.android.com/tools">
 
    <!-- binding object of ViewModel to the XML layout -->
    <data>
        <variable
            name="viewModel"
            type="com.example.mvvmarchitecture.AppViewModel" />
    </data>
 
    <!-- Provided Linear layout for the activity components -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="8dp"
        android:background="#168BC34A"
        android:orientation="vertical">
 
        <!-- TextView for the heading of the activity -->
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/heading"
            android:textAlignment="center"
            android:textColor="@android:color/holo_green_dark"
            android:textSize="36sp"
            android:textStyle="bold" />
 
        <!-- EditText field for the Email -->
        <EditText
            android:id="@+id/inEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginTop="60dp"
            android:layout_marginEnd="10dp"
            android:layout_marginBottom="20dp"
            android:hint="@string/email_hint"
            android:inputType="textEmailAddress"
            android:padding="8dp"
            android:text="@={viewModel.userEmail}" />
 
        <!-- EditText field for the password -->
        <EditText
            android:id="@+id/inPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:hint="@string/password_hint"
            android:inputType="textPassword"
            android:padding="8dp"
            android:text="@={viewModel.userPassword}" />
 
        <!-- Login Button of the activity -->
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="60dp"
            android:layout_marginEnd="20dp"
            android:background="#4CAF50"
            android:fontFamily="@font/roboto"
            android:onClick="@{()-> viewModel.onButtonClicked()}"
            android:text="@string/button_text"
            android:textColor="@android:color/background_light"
            android:textSize="30sp"
            android:textStyle="bold"
            bind:toastMessage="@{viewModel.toastMessage}" />
 
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="135dp"
            app:srcCompat="@drawable/banner" />
 
    </LinearLayout>
</layout>

Paso 5: Crear la clase ViewModel

Esta clase contendrá todos los métodos que se necesitan llamar en el diseño de la aplicación. La clase ViewModel extenderá BaseObservable porque convierte los datos en flujos y notifica a la Vista cuando cambie la propiedad del mensaje del sistema.

Java

import android.text.TextUtils;
import android.util.Patterns;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
 
public class AppViewModel extends BaseObservable {
 
    // creating object of Model class
    private Model model;
 
    // string variables for
    // toast messages
    private String successMessage = "Login successful";
    private String errorMessage = "Email or Password is not valid";
 
    @Bindable
    // string variable for
    // toast message
    private String toastMessage = null;
 
    // getter and setter methods
    // for toast message
    public String getToastMessage() {
        return toastMessage;
    }
 
    private void setToastMessage(String toastMessage) {
        this.toastMessage = toastMessage;
        notifyPropertyChanged(BR.toastMessage);
    }
 
    // getter and setter methods
    // for email variable
    @Bindable
    public String getUserEmail() {
        return model.getEmail();
    }
 
    public void setUserEmail(String email) {
        model.setEmail(email);
        notifyPropertyChanged(BR.userEmail);
    }
 
    // getter and setter methods
    // for password variable
    @Bindable
    public String getUserPassword() {
        return model.getPassword();
    }
 
    public void setUserPassword(String password) {
        model.setPassword(password);
        notifyPropertyChanged(BR.userPassword);
    }
 
    // constructor of ViewModel class
    public AppViewModel() {
 
        // instantiating object of
        // model class
        model = new Model("","");
    }
 
    // actions to be performed
    // when user clicks
    // the LOGIN button
    public void onButtonClicked() {
        if (isValid())
            setToastMessage(successMessage);
        else
            setToastMessage(errorMessage);
    }
 
    // method to keep a check
    // that variable fields must
    // not be kept empty by user
    public boolean isValid() {
        return !TextUtils.isEmpty(getUserEmail()) && Patterns.EMAIL_ADDRESS.matcher(getUserEmail()).matches()
                && getUserPassword().length() > 5;
    }
}

Paso 6: Defina las funcionalidades de View en el archivo MainActivity

La clase View es responsable de actualizar la interfaz de usuario de la aplicación. De acuerdo con los cambios en el mensaje del sistema proporcionado por ViewModel, el adaptador de enlace activaría la capa de vista. El emisor del mensaje Toast notificará al observador (Ver) sobre los cambios en los datos. Después de eso, View tomará las medidas apropiadas.

Java

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.BindingAdapter;
import androidx.databinding.DataBindingUtil;
 
import com.example.mvvmarchitecture.databinding.ActivityMainBinding;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // ViewModel updates the Model
        // after observing changes in the View
 
        // model will also update the view
        // via the ViewModel
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        activityMainBinding.setViewModel(new AppViewModel());
        activityMainBinding.executePendingBindings();
 
    }
 
    // any change in toastMessage attribute
    // defined on the Button with bind prefix
    // invokes this method
    @BindingAdapter({"toastMessage"})
    public static void runMe( View view, String message) {
        if (message != null)
            Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
    }
}

Producción

Ventajas de la arquitectura MVVM

  • Mejorar la reutilización del código.
  • Todos los módulos son independientes, lo que mejora la capacidad de prueba de cada capa.
  • Hace que los archivos del proyecto sean fáciles de mantener y realizar cambios.

Desventajas de la arquitectura MVVM

  • Este patrón de diseño no es ideal para proyectos pequeños.
  • Si la lógica de vinculación de datos es demasiado compleja, la depuración de la aplicación será un poco más difícil.

Publicación traducida automáticamente

Artículo escrito por RISHU_MISHRA 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 *