📌  相关文章
📜  Android 中的 Dagger Hilt 示例

📅  最后修改于: 2022-05-13 01:55:23.266000             🧑  作者: Mango

Android 中的 Dagger Hilt 示例

依赖注入(DI)是一种设计模式,用于解耦对象之间的常规依赖关系。在 android Dagger中的 DI 总是处于领先地位。但它非常复杂,需要大量样板代码才能设置 Dagger。因此,为了克服这个问题,引入了Hilt 。 Dagger Hilt 简化了整个过程,减少了不必要的步骤,同时又不失去原始 Dagger 的任何功能。

例子

在此示例中,我们将构建一个 android 应用程序,该应用程序将使用 MVVM 设计模式显示加密货币列表,对于依赖注入,我们将使用 Dagger Hilt。

第 1 步:创建一个新项目

要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。请注意,选择Kotlin作为编程语言。

第 2 步:添加依赖项

为了使用 Dagger Hilt,我们需要为其添加依赖项。首先,我们将类路径添加到我们的项目级 build.gradle 文件中。要添加此依赖项,请转到Gradle Scripts > build.gradle(Project:app)添加以下依赖项。添加这些依赖项后,您需要单击Sync Now

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

添加插件和依赖项后,您需要单击Sync Now 。在进一步移动之前,让我们添加一些颜色属性以增强应用栏。转到 app > res > values > colors.xml 并添加以下颜色属性。

XML

    #0F9D58
    #16E37F
    #03DAC5


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


XML

 



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


Kotlin
interface CryptocurrencyRepository {
    fun getCryptoCurrency(): List
}


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


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


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>()
    val cryptoCurrency: LiveData> = cryptocurrencyEmitter
    init {
        loadCryptocurrency()
    }
     
    // getting cryptocurrencies list using
    // repository and passing it into live data
    private fun loadCryptocurrency() {
        cryptocurrencyEmitter.value = cryptocurrencyRepository.getCryptoCurrency()
    }
}


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) : RecyclerView.Adapter()  {
    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(R.id.cryptocurrency).text = index.name
        }
    }
}


XML


   
    
   
    
    
   


XML


   
    
   


Kotlin
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    // viewModels() delegate used to get
    // ViewModel in MainActivity class
    private val viewModel:MainViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        observeCryptoCurrency()
    }
     
    // Observing the live data
    private fun observeCryptoCurrency() {
        viewModel.cryptoCurrency.observe(this) {
            viewModel.cryptoCurrency.observe(this) {
                val cryptocurrencyList = findViewById(R.id.cryptocurrency_list)
                cryptocurrencyList.layoutManager = LinearLayoutManager(this)
                cryptocurrencyList.adapter = CryptocurrencyAdapter(it)
            }
        }
    }
}


第 3 步:创建 HiltApplication 类

在这一步中,我们将创建一个HiltApplication.kt类,并使用@HiltAndroidApp注解对该类进行注解。这将使此类触发 Hilt 的代码生成,该代码生成将具有我们应用程序的基类,并充当应用程序级依赖项容器。为此,请转到app > Java > package > 右键单击 > New > Kotlin Class/File并将其命名为HiltApplication

科特林

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

完成此操作后,我们需要通过在 标记中提供 HiltApplication.kt 类名称作为 android:name 来更新我们的 AndroidManifest.xml 文件。另外,我们需要在 AndroidManifest 文件中添加 Internet 权限。

XML


 


第 4 步:创建数据类和存储库

在这一步中,首先,我们将创建一个 Data 类并将其命名为 Cryptocurrency。此类将有两个成员变量 images 和一个名称。为此,转到app > Java > package > Right-click > New > Kotlin Class/File

科特林

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

现在,我们将创建一个 Repository 类,该类将包含一些我们将注入到 ViewModel 中的示例数据。我们将把这个 Repository 抽象为一个接口并为其提供一个实现。为了创建这个转到app > Java > package > 右键单击 > New > Kotlin Class/File并将其类型设置为接口并将其名称命名为 CryptocurrencyRepository 并向其中添加以下接口代码。

科特林

interface CryptocurrencyRepository {
    fun getCryptoCurrency(): List
}

现在,我们将为这个接口类提供一个实现。为此,转到app > Java > package > 右键单击 > New > Kotlin Class/File并创建一个新类并将其命名为 CryptocurrencyRepositoryImpl.kt,在该类中,我们将覆盖 getCryptoCurrency() 方法并为其提供实现.加密货币数据类将有两个字符串类型属性,一个用于图像,另一个用于名称。

科特林

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

第 5 步:创建模块类

在这一步中,我们将创建一个模块类并将其命名为 AppModule。为此,转到app > Java > package > 右键单击 > New > Kotlin Class/File并创建一个新类并将其命名为AppModule.kt 。 AppModule 类将向其他类注入依赖,因此,我们需要使用@Module注释对此类进行注释,这将使该类成为一个模块,以向其范围内的其他类注入依赖。此外,我们还将为其添加一个注释。即, @InstallIn(SingletonComponent::class)这将使该类在整个应用程序中注入依赖项。

科特林

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

在这里,我们还使用@Provides注释添加了 CryptocurrencyRepository 的规定。除此之外,我们还使用了@Singleton注解,因此每当我们注入依赖项时,我们都会请求注入相同的单个 CryptocurrencyRepository 实例。

第 6 步:创建视图模型

在这一步中,我们将创建一个 ViewModel。为此,请转到app > Java > package > 右键单击 > New > Kotlin Class/File并创建一个新类并将其命名为 MainViewModel.kt。我们将使用@HiltViewModel 对其进行注释,这使得模型可以使用 Hilt 的模型工厂创建,从而更容易与活动和片段一起使用。我们还将使用@Inject 注解精确地注解一个构造函数,使用这个构造函数我们将所有依赖项注入到我们的视图模型类中。下面是 MainViewModel.kt 类的代码。

科特林

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>()
    val cryptoCurrency: LiveData> = cryptocurrencyEmitter
    init {
        loadCryptocurrency()
    }
     
    // getting cryptocurrencies list using
    // repository and passing it into live data
    private fun loadCryptocurrency() {
        cryptocurrencyEmitter.value = cryptocurrencyRepository.getCryptoCurrency()
    }
}

第 7 步:创建适配器类

在这一步中,我们将创建一个适配器。为此,请转到app > Java > package > 右键单击 > 新建 > Kotlin 类/文件并创建一个新类并将其命名为 CryptocurrencyAdapter.kt。这将提供对我们加密货币数据项的访问权限,并负责为加密货币数据列表中的每个项目创建一个视图。

科特林

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) : RecyclerView.Adapter()  {
    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(R.id.cryptocurrency).text = index.name
        }
    }
}

第 8 步:创建 list_item.xml 文件

在这一步中,我们将创建一个 list_item.xml 文件,其中将包含我们图像的视图和加密货币的名称。为此,转到应用 > res > 布局 > 右键单击 > 新建 > 布局资源文件并创建一个资源文件并将其命名为 list_item.xml 并向其中添加以下代码行。

XML



   
    
   
    
    
   

第 9 步:创建 activity_main.xml 文件

在这一步中,我们将为我们的 activity_main.xml 文件进行布局。我们将只添加一个 RecyclerView 到我们的布局中。

XML



   
    
   

第 10 步:使用 MainActivity 文件

最后,我们使用 MainActivity。首先,我们使用@AndroidEntryPoint注解对其进行注解,这将使组件类(活动、片段、视图、服务和广播接收器)准备好进行注入。此外,我们将通过 viewModles() 委托在 MainActivity 中获取我们的 ViewModel。之后,我们只是观察我们的 LiveData。

科特林

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    // viewModels() delegate used to get
    // ViewModel in MainActivity class
    private val viewModel:MainViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        observeCryptoCurrency()
    }
     
    // Observing the live data
    private fun observeCryptoCurrency() {
        viewModel.cryptoCurrency.observe(this) {
            viewModel.cryptoCurrency.observe(this) {
                val cryptocurrencyList = findViewById(R.id.cryptocurrency_list)
                cryptocurrencyList.layoutManager = LinearLayoutManager(this)
                cryptocurrencyList.adapter = CryptocurrencyAdapter(it)
            }
        }
    }
}

输出: