La inyección de dependencia (DI) es un patrón de diseño para desacoplar la relación de dependencia convencional entre objetos. Cuando se trata de DI en Android, Dagger siempre toma la delantera. Pero es muy complejo y requiere muchos códigos repetitivos para configurar la Daga. Entonces, para superar este problema , se introdujo Hilt . Dagger Hilt simplifica todo el proceso y reduce los pasos innecesarios sin perder ninguna de las características del Dagger original.
Ejemplo
En este ejemplo, crearemos una aplicación para Android que mostrará la lista de criptomonedas usando el patrón de diseño MVVM y para la inyección de dependencia, usaremos Dagger Hilt.
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: Agregar dependencias
Para usar Dagger Hilt, necesitamos agregar las dependencias para ello. Primero, agregaremos el classpath a nuestro archivo build.gradle a nivel de proyecto . Para agregar esta dependencia, vaya a Gradle Scripts > build.gradle(Project:app) y agregue la siguiente dependencia. Después de agregar estas dependencias, debe hacer clic en Sincronizar ahora .
dependencies { classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1' }
Ahora, en el archivo build.gradle a nivel de la aplicación, debemos colocar un complemento. Para esto, vaya a Gradle Scripts > build.gradle(Module:app) agregue el siguiente complemento.
plugins { id 'kotlin-android' id 'kotlin-kapt' id 'dagger.hilt.android.plugin' }
También necesitamos agregar la dependencia en el mismo archivo build.gradle de nivel de aplicación. La siguiente dependencia debe agregarse dentro de build.gradle (Módulo: aplicación).
dependencies { implementation 'com.github.bumptech.glide:glide:4.9.0' implementation 'com.google.dagger:hilt-android:2.38.1' kapt 'com.google.dagger:hilt-android-compiler:2.38.1' kapt 'androidx.hilt:hilt-compiler:1.0.0' implementation "androidx.activity:activity-ktx:1.4.0" }
También necesitamos agregar atributos de propiedad en el archivo gradle.properties . Vaya a Gradle Scripts > gradle.properties y agregue la siguiente propiedad.
kapt.use.worker.api=false
Después de agregar complementos y dependencias, debe hacer clic en Sincronizar ahora . 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: crear una clase HiltApplication
En este paso, crearemos una clase HiltApplication.kt y anotaremos esta clase con anotaciones @HiltAndroidApp . Esto hará que esta clase desencadene la generación de código de Hilt, que tendrá la clase base para nuestra aplicación y actuará como el contenedor de dependencias a nivel de la aplicación. Para esto, vaya a app > java > package > haga clic con el botón derecho en > New > Kotlin Class/File y asígnele el nombre HiltApplication .
Kotlin
import android.app.Application import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp class HiltApplication :Application(){ }
Una vez que hayamos terminado con esto, debemos actualizar nuestro archivo AndroidManifest.xml proporcionando nuestro nombre de clase HiltApplication.kt como android:name dentro de la etiqueta <application></application>. Además, debemos agregar el permiso de Internet en el archivo AndroidManifest.
XML
<uses-permission android:name="android.permission.INTERNET" /> <application android:name=".HiltApplication" > </application>
Paso 4: crear una clase de datos y un repositorio
En este paso, primero, crearemos una clase de Datos y la llamaremos Criptomoneda. Esta clase tendrá dos imágenes de variables miembro y un nombre. Para esto, vaya a app > java > package > Haga clic con el botón derecho en > New > Kotlin Class/File .
Kotlin
data class Cryptocurrency( val image:String, val name:String )
Ahora, crearemos una clase de Repositorio que tendrá algunos datos de muestra que inyectaremos en nuestro ViewModel. Haremos que este Repositorio sea abstracto convirtiéndolo en una interfaz y brindándole una implementación. Para crear esto, vaya a aplicación > java > paquete > haga clic con el botón derecho en > Nuevo > Clase/Archivo Kotlin y haga su tipo como interfaz y asigne su nombre como CryptocurrencyRepository y agregue el siguiente código de interfaz.
Kotlin
interface CryptocurrencyRepository { fun getCryptoCurrency(): List<Cryptocurrency> }
Ahora, proporcionaremos una implementación para esta clase de interfaz. Para esto, vaya a aplicación> java> paquete> clic derecho> Nuevo> Clase/archivo Kotlin y cree una nueva clase y asígnele el nombre CryptocurrencyRepositoryImpl.kt. En esta clase, anularemos el método getCryptoCurrency() y le proporcionaremos una implementación. . La clase de datos de criptomonedas tendrá dos atributos de tipo string, uno para la imagen y otro para el nombre.
Kotlin
class CryptocurrencyRepositoryImpl : CryptocurrencyRepository{ // Overriding the interface method and // providing implementation to it override fun getCryptoCurrency() = listOf( // here we are adding images from wikipedia Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/BTC_Logo.svg/1200px-BTC_Logo.svg.png", "BitCoin"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Ethereum_logo_translucent.svg/1200px-Ethereum_logo_translucent.svg.png", "Ethereum"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/thumb/1/12/Binance_logo.svg/1920px-Binance_logo.svg.png", "Binance"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/en/d/d0/Dogecoin_Logo.png", "DogeCoin"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Litecoin_Logo.jpg/2048px-Litecoin_Logo.jpg", "LiteCoin"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/5/56/Stellar_Symbol.png", "Stellar"), Cryptocurrency("https://upload.wikimedia.org/wikipedia/commons/5/59/Polkadot_Logotype_color.png", "Polkadot"), ) }
Paso 5: crear una clase de módulo
En este paso, crearemos una clase de módulo y la nombraremos AppModule. Para esto, vaya a app > java > package > Right-click > New > Kotlin Class/File y cree una nueva clase y asígnele el nombre AppModule.kt . La clase AppModule inyectará dependencia a otras clases, por lo que debemos anotar esta clase con la anotación @Module que hará de esta clase un módulo para inyectar dependencia a otras clases dentro de su alcance. Además, también le agregaremos una anotación más. es decir, @InstallIn(SingletonComponent::class) esto hará que esta clase inyecte dependencias en toda la aplicación.
Kotlin
import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton // @Module annotation which will make this class a module // to inject dependency to other class within it's scope. // @InstallIn(SingletonComponent::class) this will make // this class to inject dependencies across the entire application. @Module @InstallIn(SingletonComponent::class) class AppModule { @Provides @Singleton fun provideCryptocurrencyRepository():CryptocurrencyRepository=CryptocurrencyRepositoryImpl() }
Aquí, también hemos agregado la provisión para CryptocurrencyRepository usando la anotación @Provides . Junto con esto, hemos utilizado la anotación @Singleton para que cada vez que inyectemos la dependencia, inyectemos la misma instancia única de CryptocurrencyRepository que alguna vez se solicitó.
Paso 6: Creación de un modelo de vista
En este paso, crearemos un ViewModel . Para hacerlo, vaya a aplicación > java > paquete > haga clic con el botón derecho en > Nuevo > Clase/Archivo de Kotlin y cree una nueva clase y asígnele el nombre MainViewModel.kt. Lo anotaremos con @HiltViewModel, que hace que los modelos se creen utilizando la fábrica de modelos de Hilt, lo que facilita su uso con Actividades y Fragmentos . También anotaremos exactamente un constructor con la anotación @Inject, usando este constructor inyectaremos todas las dependencias a nuestra clase de modelo de vista. A continuación se muestra el código de la clase MainViewModel.kt.
Kotlin
import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject // @HiltViewModel will make models to be // created using Hilt's model factory // @Inject annotation used to inject all // dependencies to view model class @HiltViewModel class MainViewModel @Inject constructor( private val cryptocurrencyRepository: CryptocurrencyRepository ) : ViewModel() { private val cryptocurrencyEmitter = MutableLiveData<List<Cryptocurrency>>() val cryptoCurrency: LiveData<List<Cryptocurrency>> = cryptocurrencyEmitter init { loadCryptocurrency() } // getting cryptocurrencies list using // repository and passing it into live data private fun loadCryptocurrency() { cryptocurrencyEmitter.value = cryptocurrencyRepository.getCryptoCurrency() } }
Paso 7: crear una clase de adaptador
En este paso, crearemos un adaptador. Para hacerlo, vaya a aplicación > java > paquete > clic derecho > Nuevo > Clase/Archivo Kotlin y cree una nueva clase y asígnele el nombre CryptocurrencyAdapter.kt. Esto proporcionará acceso a nuestros elementos de datos de criptomonedas y será responsable de hacer una Vista para cada elemento en la lista de datos de criptomonedas.
Kotlin
import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide class CryptocurrencyAdapter(private val cryptocurrency: List<Cryptocurrency>) : RecyclerView.Adapter<CryptocurrencyAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { // Inflating list data from list_item to view val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) return ViewHolder(view) } // Binding cryptocurrency list to ViewHolder override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.bind(cryptocurrency[position]) } override fun getItemCount() = cryptocurrency.size // Iterating ViewHolder and loading it's // content to our Image and Text ViewsT class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(index: Cryptocurrency) { // Here, we are using Glide library to // load the image into ImageView Glide.with(itemView.context) .load(index.image).dontAnimate() .into(itemView.findViewById(R.id.image)) // Setting name of cryptocurrency to TextView itemView.findViewById<TextView>(R.id.cryptocurrency).text = index.name } } }
Paso 8: Cree el archivo list_item.xml
En este paso, crearemos un archivo list_item.xml que contendrá las vistas de nuestra imagen y el nombre de la criptomoneda. Para esto, vaya a aplicación > res > diseño > haga clic con el botón derecho en > Nuevo > Archivo de recursos de diseño y cree un archivo de recursos y asígnele el nombre list_item.xml y agréguele las siguientes líneas de códigos.
XML
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:layout_margin="8dp" android:background="#f5f5f5" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"> <ImageView android:id="@+id/image" android:layout_width="64dp" android:layout_height="64dp" android:scaleType="fitXY" android:layout_margin="24dp" android:importantForAccessibility="no" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> <!--text used are only for understanding purpose it will be removed at the runtime--> <TextView android:id="@+id/cryptocurrency" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="24dp" android:textSize="24sp" app:layout_constraintStart_toEndOf="@id/image" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" tools:text="Cryptocurrencies" /> </androidx.constraintlayout.widget.ConstraintLayout>
Paso 9: Cree el archivo activity_main.xml
En este paso, haremos el diseño de nuestro archivo activity_main.xml. Simplemente agregaremos un RecyclerView a nuestro diseño.
XML
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/cryptocurrency_list" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Paso 10: Trabajar con el archivo MainActivity
Finalmente, trabajamos con nuestra MainActivity. Primero, lo anotamos con la anotación @AndroidEntryPoint que hará que la clase del componente (actividad, fragmentos, vistas, servicios y receptor de transmisión) esté lista para la inyección. Además, obtendremos nuestro ViewModel en MainActivity mediante el uso del delegado viewModles(). Después de eso, solo estamos observando nuestro LiveData.
Kotlin
@AndroidEntryPoint class MainActivity : AppCompatActivity() { private lateinit var cryptocurrencyList: RecyclerView // viewModels() delegate used to get // by view models will automatically construct the viewmodels using Hilt private val viewModel:MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) cryptocurrencyList = findViewById<RecyclerView>(R.id.cryptocurrency_list) cryptocurrencyList.layoutManager = LinearLayoutManager(this) observeCryptoCurrency() } // Observing the live data private fun observeCryptoCurrency() { viewModel.cryptoCurrency.observe(this) { cryptocurrencyList.adapter = CryptocurrencyAdapter(it) } } }
Producción: