Inyección de dependencia con Dagger 2 en Android

Si hay dos clases, la clase A y la clase B, y la clase A depende de la clase B , entonces la clase B se llama dependiente de la clase A.

Entonces, cada vez que queremos acceder a la clase B en la clase A, necesitamos crear una instancia de la clase B en la clase A o usar métodos estáticos de fábrica para acceder a la clase A. Pero esto hará que nuestro código esté estrechamente acoplado, sea difícil de administrar y probar. . Para eliminar estos problemas, usamos la inyección de dependencia. La inyección de dependencia es un patrón de diseño que elimina la dependencia del código de programación y hace que la aplicación sea fácil de administrar y probar. También hace que el código de programación esté débilmente acoplado.

Inyección de dependencia en Android

Supongamos que queremos almacenar algunos datos en SharedPreferences . Para guardar o recuperar datos de preferencias compartidas, necesitamos la instancia de preferencia compartida en el código repetitivo de nuestra Actividad. Y puede generar problemas en las pruebas, la gestión, etc. si nuestra base de código es grande. Aquí es donde ayuda la inyección de dependencia de Android. Aquí, SharedPreferences actúa como una dependencia para nuestra actividad, por lo que no creamos su instancia en nuestra actividad, sino que la inyectamos desde alguna otra clase. A continuación se muestra una ilustración de la situación.

Daga 2

Dagger 2 es un marco de inyección de dependencia de Android en tiempo de compilación que utiliza Java Specification Request 330 y Annotations . Algunas de las anotaciones básicas que se utilizan en daga 2 son:

  1. @Module Esta anotación se usa sobre la clase que se usa para construir objetos y proporcionar las dependencias.
  2. @Provides Esto se usa sobre el método en la clase de módulo que devolverá el objeto.
  3. @Inject Esto se usa sobre los campos, el constructor o el método e indica que se solicitan las dependencias.
  4. @Component Esto se usa sobre una interfaz de componente que actúa como un puente entre @Module e @Inject. (La clase del módulo no proporciona dependencia directamente a la clase solicitante, usa la interfaz del componente)
  5. @Singleton Esto se usa para indicar que solo se crea una única instancia de objeto de dependencia.

Ejemplo

En este ejemplo, agregaremos algunos datos a las preferencias compartidas y luego los recuperaremos desde allí usando la biblioteca dagger 2 . A continuación se muestra la imagen de lo que vamos a hacer en este ejemplo. Java

Implementación paso a paso

Paso 1: Crear un nuevo proyecto

Cómo crear/iniciar un nuevo proyecto en Android Studio Java

Paso 2: agregar dependencias

Para usar la inyección de dependencia con la ayuda de las bibliotecas dagger 2, debemos agregar su dependencia. Vaya a Gradle Scripts > build.gradle(Module: app) y agregue las siguientes dependencias. Después de agregar estas dependencias, debe hacer clic en Sincronizar ahora .

dependencias {

  implementación “com.google.dagger:hilt-core:2.29-alpha”

  anotaciónProcesador «com.google.dagger:hilt-compiler:2.29-alpha»

}

Antes de continuar, agreguemos algunos atributos de color para mejorar la barra de la aplicación. Vaya a aplicación > res > valores > colores.xml y agregue los siguientes atributos de color.  

XML

<resources> 
    <color name="colorPrimary">#0F9D58</color> 
    <color name="colorPrimaryDark">#16E37F</color> 
    <color name="colorAccent">#03DAC5</color> 
</resources> 

Paso 3: trabajar con el archivo activity_main.xml

En este paso, crearemos un archivo de diseño para la aplicación. Hemos utilizado EditText para tomar la entrada del usuario y TextView para presentar la salida y guardar y mostrar los botones respectivamente. A continuación se muestra el fragmento de código para el archivo activity_main.xml .

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <Button
        android:id="@+id/saveBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/inputField"
        android:layout_centerInParent="true"
        android:layout_margin="8dp"
        android:background="@color/colorPrimary"
        android:text="Save"
        android:textColor="#ffffff" />
  
    <Button
        android:id="@+id/getBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/outputField"
        android:layout_centerInParent="true"
        android:layout_margin="8dp"
        android:background="@color/colorPrimary"
        android:text="Show"
        android:textColor="#ffffff" />
  
    <!--For input we have used EditText-->
    <EditText
        android:id="@+id/inputField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:hint="Input Data"
        android:textAlignment="center" />
  
    <!--For output we have used TextView-->
    <TextView
        android:id="@+id/outputField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/saveBtn"
        android:layout_margin="8dp"
        android:hint="Output Data"
        android:textAlignment="center" />
  
</RelativeLayout>

Paso 4: crear una clase de módulo

Ahora, crearemos una clase de módulo que se usa para construir el objeto y proporcionar las dependencias. Las anotaciones @Module se utilizan sobre la clase de módulo. Esta clase contiene un constructor que inicializará el contexto y un método que devolverá el objeto dependiente para el que se usa la anotación @Provides . Aquí, el método provideSharedPreferences() devolverá el objeto dependiente. En general, el método que devuelve el objeto dependiente irá seguido de la palabra provide. Vaya a la aplicación > java > paquete > haga clic con el botón derecho y cree una nueva clase java y asígnele el nombre SharedPreferenceModule . A continuación se muestra el fragmento de código del archivo SharedPreferenceModule.java .

Java

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
  
// @Module annotation is used over the class that 
// creates construct object and provides dependencies
@Module
public class SharedPreferenceModule {
    private Context context;
  
    // Context gets initialize from the constructor itself
    public SharedPreferenceModule(Context context) {
        this.context = context;
    }
  
    @Singleton
    @Provides
    public Context provideContext() {
        return context;
    }
  
    // @Singleton indicates that only single instance 
    // of dependency object is created
    // @Provide annotations used over the methods that
    // will provides the object of module class
    // This method will return the dependent object
    @Singleton
    @Provides
    public SharedPreferences provideSharedPreferences(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }
}

Paso 5: Creación de una interfaz de componentes

En este paso, crearemos una interfaz. Vaya a la aplicación > java > paquete > haga clic con el botón derecho y cree una interfaz y asígnele el nombre SharedPreferenceComponent . Usamos la anotación @Component para mencionar todos los módulos. 

@Component(módulos={MóduloPreferenciaCompartida})
 

Las Actividades, Fragmentos o Servicios que puedan solicitar las dependencias declaradas por los módulos deben declararse en esta interfaz con el método inject() individual. A continuación se muestra el fragmento de código para la interfaz SharedPreferenceComponent.java .

Java

import javax.inject.Singleton;
import dagger.Component;
  
// All the modules are mentioned under 
// the @Component annotation
@Singleton
@Component(modules = {SharedPreferenceModule.class})
public interface SharedPreferenceComponent {
    void inject(MainActivity mainActivity);
}

Paso 6: trabajar con el archivo MainActivity.java

En este paso, primero inicializaremos nuestras vistas y luego vincularemos Dagger a nuestra aplicación. Para qué componente-interfaz va seguida de la palabra clave Dagger.

sharedPreferenceComponent = DaggerSharedPreferenceComponent.builder().sharedPreferenceModule(new SharedPreferenceModule(this)).build();

sharedPreferenceComponent.inject(esto);

A continuación se muestra el fragmento de código del archivo MainActivity.java .

Nota: Cuando use Dagger como prefijo con Componente (aquí, SharedPreferenceComponent), a veces puede recibir un error o una advertencia, esto se debe a que DaggerSharedPreferenceComponent se genera después de la compilación.

Java

import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import javax.inject.Inject;
  
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  
    EditText editText;
    TextView textView;
    Button saveBtn, getBtn;
    private SharedPreferenceComponent sharedPreferenceComponent;
  
    // @Inject is used to tell which activity, 
    // fragment or service is allowed to request
    // dependencies declared in Module class
    @Inject
    SharedPreferences sharedPreferences;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        // Referencing the EditText, TextView and Buttons
        editText = (EditText) findViewById(R.id.inputField);
        textView = (TextView) findViewById(R.id.outputField);
        saveBtn = (Button) findViewById(R.id.saveBtn);
        getBtn = (Button) findViewById(R.id.getBtn);
  
        // Setting onClickListener behavior on button to reference
        // to the current activity(this MainActivity)
        saveBtn.setOnClickListener(this);
        getBtn.setOnClickListener(this);
  
        // Here we are binding dagger to our application
        // Dagger keyword will be prefix to the component name
        sharedPreferenceComponent = DaggerSharedPreferenceComponent.builder().sharedPreferenceModule(
                new SharedPreferenceModule(this)).build();
          
        // we are injecting the shared preference dependent object
        sharedPreferenceComponent.inject(this);
    }
  
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.saveBtn:
                // Saving data to shared preference
                // inputField acts as key and editText data as value to that key
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString("inputField", editText.getText().toString().trim());
                editor.apply();
                break;
            case R.id.getBtn:
                // getting shared preferences data and set it to textview
                // s1: is the default string, You can write any thing there or leave it
                textView.setText(sharedPreferences.getString("inputField", ""));
                break;
        }
    }
}

Salida: ejecutar en el emulador

Publicación traducida automáticamente

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