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(){
}
完成此操作后,我们需要通过在
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)
}
}
}
}
输出: