Рукоять кинжала в Android с примером

Опубликовано: 3 Сентября, 2022

Внедрение зависимостей (DI) — это шаблон проектирования для разделения обычных отношений зависимости между объектами. Когда дело доходит до DI в Android, Dagger всегда лидирует. Но это очень сложно и требует много стандартных кодов для настройки Dagger. Итак, чтобы преодолеть эту проблему, была введена рукоять . Dagger Hilt упрощает весь процесс и сокращает количество ненужных шагов, не теряя при этом никаких функций оригинального Dagger.

Пример

В этом примере мы создадим приложение для Android, которое будет отображать список криптовалют, используя шаблон проектирования MVVM, а для внедрения зависимостей мы будем использовать Dagger Hilt.

Шаг 1: Создайте новый проект

Чтобы создать новый проект в Android Studio, обратитесь к разделу «Как создать/запустить новый проект в Android Studio». Обратите внимание, что выберите Kotlin в качестве языка программирования.

Шаг 2: Добавление зависимостей

Чтобы использовать Dagger Hilt, нам нужно добавить для него зависимости. Во-первых, мы добавим classpath в наш файл build.gradle на уровне проекта . Чтобы добавить эту зависимость, перейдите в Gradle Scripts > build.gradle(Project:app) и добавьте следующую зависимость. После добавления этих зависимостей вам нужно нажать «Синхронизировать сейчас» .

dependencies {
        classpath "com.google.dagger:hilt-android-gradle-plugin:2.38.1"
    }

Теперь в файле build.gradle уровня приложения нам нужно разместить плагин. Для этого перейдите в Gradle Scripts > build.gradle(Module:app) и добавьте следующий плагин.

plugins {
    id "kotlin-android"
    id "kotlin-kapt"
    id "dagger.hilt.android.plugin"
}

Нам также нужно добавить зависимость в тот же файл build.gradle уровня приложения. В build.gradle(Module:app) необходимо добавить следующую зависимость.

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"
}

Нам также нужно добавить атрибуты свойств в файл gradle.properties . Перейдите в Gradle Scripts > gradle.properties и добавьте следующее свойство.

kapt.use.worker.api=false

После добавления плагинов и зависимостей нужно нажать «Синхронизировать сейчас» . Прежде чем двигаться дальше, давайте добавим некоторые цветовые атрибуты, чтобы улучшить панель приложения. Перейдите в приложение > res > values > colors.xml и добавьте следующие атрибуты цвета.

XML




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

Шаг 3: Создание класса HiltApplication

На этом этапе мы создадим класс HiltApplication.kt и аннотируем этот класс аннотациями @HiltAndroidApp . Это заставит этот класс запускать генерацию кода Hilt, который будет иметь базовый класс для нашего приложения и действовать как контейнер зависимостей на уровне приложения. Для этого перейдите в app > java > package > щелкните правой кнопкой мыши > New > Kotlin Class/File и назовите его HiltApplication .

Kotlin




import android.app.Application
import dagger.hilt.android.HiltAndroidApp
 
@HiltAndroidApp
class HiltApplication :Application(){
}

Как только мы закончим с этим, нам нужно обновить наш файл AndroidManifest.xml, указав имя нашего класса HiltApplication.kt как android:name внутри тега <application></application>. Кроме того, нам нужно добавить разрешение на доступ в Интернет в файле AndroidManifest.

XML




<uses-permission android:name="android.permission.INTERNET" />
 
<application
        android:name=".HiltApplication" >
</application>

Шаг 4: Создание класса данных и репозитория

На этом шаге сначала мы создадим класс Data и назовем его Cryptocurrency. Этот класс будет иметь два изображения переменных-членов и имя. Для этого перейдите в app > java > package > щелкните правой кнопкой мыши > New > Kotlin Class/File .

Kotlin




data class Cryptocurrency(
    val image:String,
    val name:String
)

Теперь мы создадим класс Repository, в котором будет несколько примеров данных, которые мы введем в нашу ViewModel. Мы сделаем этот репозиторий абстрактным, сделав его интерфейсом и предоставив ему реализацию. Для создания этого перейдите в приложение > java > package > Щелкните правой кнопкой мыши > New > Kotlin Class/File и сделайте его тип интерфейсом, дайте ему имя CryptocurrencyRepository и добавьте к нему следующий код интерфейса.

Kotlin




interface CryptocurrencyRepository {
    fun getCryptoCurrency(): List<Cryptocurrency>
}

Теперь мы обеспечим реализацию этого класса интерфейса. Для этого перейдите в приложение > java > package > щелкните правой кнопкой мыши > New > Kotlin Class/File и создайте новый класс и назовите его CryptocurrencyRepositoryImpl.kt. В этом классе мы переопределим метод getCryptoCurrency() и предоставим ему реализацию. . Класс данных криптовалюты будет иметь два атрибута строкового типа: один для изображения, а другой для имени.

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/en/d/d0/Dogecoin_Logo.png", "DogeCoin"),
    )
}

Шаг 5: Создание класса модуля

На этом шаге мы создадим класс модуля и назовем его AppModule. Для этого перейдите в app > java > package > щелкните правой кнопкой мыши > New > Kotlin Class/File и создайте новый класс и назовите его AppModule.kt . Класс AppModule будет внедрять зависимость в другие классы, поэтому нам нужно аннотировать этот класс аннотацией @Module , которая сделает этот класс модулем для внедрения зависимости в другие классы в пределах его области. Кроме того, мы также добавим к нему еще одну аннотацию. то есть, @InstallIn(SingletonComponent::class) заставит этот класс внедрять зависимости во всё приложение.

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()
}

Здесь мы также добавили положение для CryptocurrencyRepository, используя аннотацию @Provides . Наряду с этим мы использовали аннотацию @Singleton , чтобы всякий раз, когда мы внедряем зависимость, мы вводили один и тот же единственный экземпляр CryptocurrencyRepository, который когда-либо запрашивался.

Шаг 6: Создание ViewModel

На этом шаге мы создадим ViewModel. Для этого перейдите в приложение > java > пакет > Щелкните правой кнопкой мыши > Создать > Класс/файл Kotlin , создайте новый класс и назовите его MainViewModel.kt. Мы аннотируем его с помощью @HiltViewModel , что позволяет создавать модели с использованием фабрики моделей Hilt, что упрощает использование с действиями и фрагментами. Мы также аннотируем только один конструктор с помощью аннотации @Inject, используя этот конструктор, мы будем внедрять все зависимости в наш класс модели представления. Ниже приведен код класса 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()
    }
}

Шаг 7: Создайте класс адаптера

На этом шаге мы создадим адаптер. Для этого перейдите в приложение > java > пакет > Щелкните правой кнопкой мыши > Создать > Класс/файл Kotlin , создайте новый класс и назовите его CryptocurrencyAdapter.kt. Это обеспечит доступ к нашим элементам данных о криптовалюте и будет отвечать за создание представления для каждого элемента в списке данных о криптовалюте.

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
        }
    }
}

Шаг 8: Создайте файл list_item.xml

На этом шаге мы создадим файл list_item.xml, который будет содержать представления для нашего изображения и название криптовалюты. Для этого перейдите в приложение > res > layout > щелкните правой кнопкой мыши > New > Layout Resource File и создайте файл ресурсов, назовите его list_item.xml и добавьте в него следующие строки кода.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
   
    <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>

Шаг 9: Создайте файл activity_main.xml

На этом этапе мы создадим макет для нашего файла activity_main.xml. Мы просто добавим RecyclerView в наш макет.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
    &n