Android Hilt依賴注入的使用講解
什么是依賴注入
首先,某個(gè)類的成員變量稱為依賴,如若此變量想要實(shí)例化引用其類的方法,可以通過構(gòu)造函數(shù)傳參或者通過某個(gè)方法獲取對象,此等通過外部方法獲取對象實(shí)例的稱為依賴注入;而依賴注入又可以簡單分為手動(dòng)注入和自動(dòng)注入兩種方式;Hilt就是基于Dagger進(jìn)行場景化優(yōu)化的一個(gè)依賴注入庫,Hilt是Google專門為Android平臺(tái)打造的一個(gè)依賴注入庫,在使用上極大程度進(jìn)行啦簡化(與dagger相比)
使用依賴注入的好處
Google文檔中介紹的優(yōu)勢如下:
- 重用代碼
- 易于重構(gòu)
- 易于測試
簡單來說,在開發(fā)中某些內(nèi)容需要進(jìn)行層層手動(dòng)調(diào)用,而且需要手動(dòng)進(jìn)行實(shí)例化;對于Hilt而言,它可以自動(dòng)進(jìn)行依賴注入,并且為項(xiàng)目中的每個(gè) Android 類提供容器并自動(dòng)管理其生命周期;某些需要全局使用的數(shù)據(jù),可以通過Hilt進(jìn)行共享,從而簡化代碼
Hilt中常用的預(yù)定義限定符
@HiltAndroidApp
所有使用 Hilt 的應(yīng)用都必須包含一個(gè)帶有 @HiltAndroidApp 注解的 Application 類。@HiltAndroidApp 會(huì)觸發(fā) Hilt 的代碼生成操作,生成的代碼包括應(yīng)用的一個(gè)基類,該基類充當(dāng)應(yīng)用級依賴項(xiàng)容器,記得此Application類要在清單文件中進(jìn)行引用
@HiltAndroidApp
class App : Application() { ... }
@AndroidEntryPoint
如果某個(gè)Activity要使用Hilt依賴注入,就必須給Activity添加@AndroidEntryPoint注解,同理Activity中的某個(gè)Fragment也需要使用,也必須添加@AndroidEntryPoint注解;
目前Hilt 支持以下 Android 類:
- Application(通過使用 @HiltAndroidApp)
- ViewModel(通過使用 @HiltViewModel)
- Activity
- Fragment
- View
- Service
- BroadcastReceiver
@AndroidEntryPoint
class MainActivity : ComponentActivity() {...}
@Module
Hilt帶有一個(gè)模塊的類,使用@Module注解的類,它會(huì)告知Hilt,它提供了哪些實(shí)例,通常和@Provider搭配使用,必須通過@InstallIn注解為其添加作用域
@InstallIn
對于您可以從中執(zhí)行字段注入的每個(gè) Android 類,都有一個(gè)關(guān)聯(lián)的 Hilt 組件,您可以在 @InstallIn 注解中引用該組件。每個(gè) Hilt 組件負(fù)責(zé)將其綁定注入相應(yīng)的 Android 類。
| Android 組件 | 默認(rèn)綁定 |
|---|---|
| SingletonComponent | Application |
| ActivityRetainedComponent | Application |
| ViewModelComponent | SavedStateHandle |
| ActivityComponent | Application 和 Activity |
| FragmentComponent | Application、Activity 和 Fragment |
| ViewComponent | Application、Activity 和 View |
| ViewWithFragmentComponent | Application、Activity、Fragment 和 View |
| ServiceComponent | Application 和 Service |
@Module
@InstallIn(SingletonComponent::class)
object AppModule {...}
@Provides
如果想要讓Hilt知道,提供了哪些實(shí)例對象,可以使用@Provides進(jìn)行注解,以下提供啦一個(gè)數(shù)據(jù)庫實(shí)例,并且作用域是全局單例
@Provides
@Singleton
fun providerAccountBean():AccountBean{
return AccountBean("FranzLiszt","123456")
}
@Inject
如果想要使用Hilt自動(dòng)進(jìn)行啦依賴注入的對象,可以使用@Inject注解進(jìn)行調(diào)用;如下,無需進(jìn)行實(shí)例化,它會(huì)自動(dòng)引用providerAccountBean()提供的對象
@Inject lateinit var bean: AccountBean
@HiltViewModel
通過名稱就可以了解,它需要與ViewModel類聯(lián)合使用,作用于ViewModel上;如下,與@Inject結(jié)合使用,在構(gòu)造函數(shù)引用啦上述Hilt提供的對象
@HiltViewModel
class AccountViewModel @Inject constructor(private val bean: AccountBean):ViewModel() {...}
Hilt的使用
依賴
第一步:在project/build.gradle中添加如下代碼
plugins {
...
id 'com.google.dagger.hilt.android' version '2.44' apply false
}
第二步:在app/build.gradle中添加如下代碼
plugins {
...
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
第三步:在app/build.gradle中添加如下代碼
//Dagger - Hilt
implementation("com.google.dagger:hilt-android:2.44")
kapt("com.google.dagger:hilt-android-compiler:2.44")// Compose dependencies
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-beta01"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0-alpha03"
第四步:在app/build.gradle中添加如下代碼
android{
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
建立實(shí)體類
data class AccountBean(var username:String,var password:String)
添加Hilt入口
@HiltAndroidApp
class APP:Application() {}
提供對象
此處作為用例,只是簡單寫一個(gè)測試用例,在函數(shù)中可以編寫復(fù)雜的程序,并不會(huì)影響程序性能,在程序初始化編譯時(shí)會(huì)耗時(shí)一丟丟。一下提供啦單例AccountBean對象
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun providerAccountBean():AccountBean{
return AccountBean("FranzLiszt","123456")
}
}
獲取對象
給Activity添加HiltAndroidEntryPoint注解,然后可以通過Inject注解獲取上面providerAccountBean方法提供的對象
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject lateinit var bean: AccountBean
...
}
然后就可以直接進(jìn)行對象引用
@Composable
fun showAccountInfo() {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = bean.username)
Spacer(modifier = Modifier.height(20.dp))
Text(text = bean.password)
}
}
應(yīng)用與ViewModel中
在ViewModel中使用HiltViewModel注解,然后就可以使用Inject注解獲取Hilt自動(dòng)注入依賴的對象
@HiltViewModel
class AccountViewModel @Inject constructor(private val bean: AccountBean):ViewModel() {...}
定義兩個(gè)具有狀態(tài)的成員變量,其中AccountState是一個(gè)數(shù)據(jù)類,具有text和hint兩個(gè)成員變量
private val _usernameState = mutableStateOf(AccountState(
hint = "input username"
))
val usernameState:State<AccountState> = _usernameState
private val _passwordState = mutableStateOf(AccountState(
hint = "input password"
))
val passwordState:State<AccountState> = _passwordState
在ViewModel初始化函數(shù)中,將Hilt提供的對象的值賦值給VM中的兩個(gè)狀態(tài)變量
init {
_usernameState.value = usernameState.value.copy(text = bean.username)
_passwordState.value = passwordState.value.copy(text = bean.password)
}
通過外部事件進(jìn)行對應(yīng)處理,外部輸入框不斷進(jìn)行值修改,此處同步給VM中的狀態(tài)變量
fun onEvent(event: AccountEvent){
when(event){
is AccountEvent.ChangeUsername ->{
_usernameState.value = usernameState.value.copy(text = event.value)
}
is AccountEvent.ChangePassword ->{
_passwordState.value = passwordState.value.copy(text = event.value)
}
}
}
使用
此處直接獲取ViewModel的兩個(gè)成員變量值,然后與兩個(gè)輸入框進(jìn)行綁定,通過監(jiān)聽輸入框的onValueChange方法,當(dāng)其值不斷修改時(shí),然后調(diào)用VM中的onEvent方法,然后修改VM中的狀態(tài)內(nèi)容,由于輸入框綁定了VM的狀態(tài)變量,然后狀態(tài)變量值改變后,相對應(yīng)的UI界面會(huì)進(jìn)行重組
@Composable
fun showAccountInfo (viewModel: AccountViewModel = hiltViewModel()){
val username = viewModel.usernameState.value
val password = viewModel.passwordState.value
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
value = username.text,
placeholder = { Text(text = username.hint)},
onValueChange = {
viewModel.onEvent(AccountEvent.ChangeUsername(it))
}
)
Spacer(modifier = Modifier.height(20.dp))
TextField(
value = password.text,
placeholder = { Text(text = password.hint)},
onValueChange = {
viewModel.onEvent(AccountEvent.ChangePassword(it))
}
)
}
}
總結(jié)
上述的倆個(gè)測例,只是使用Hilt提供的便利的冰山一角;Hilt使用起來很方便,而去可以提高代碼結(jié)構(gòu),省去不必要的代碼;其中Koin依賴注入庫也備受好評,雖然我沒有使用過,因?yàn)镚oogle推Hilt,就首先入手啦;在性能上,我看了一些其他文章上介紹,大差不差的,所有根據(jù)自己需要進(jìn)行選擇。
到此這篇關(guān)于Android Hilt依賴注入的使用講解的文章就介紹到這了,更多相關(guān)Android Hilt依賴注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?WebView緩存機(jī)制優(yōu)化加載慢問題
我知道你一定在煩惱Android?Webview的性能問題,特別突出的是-加載速度慢、消耗流量,針對Android?Webview的性能問題,提出一些有效解決方案2023-02-02
android側(cè)滑菜單控件DrawerLayout使用方法詳解
這篇文章主要為大家詳細(xì)介紹了android側(cè)滑菜單控件DrawerLayout的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android?TextView的maxEms和maxLength屬性區(qū)別
這篇文章主要為大家介紹了Android?TextView的maxEms和maxLength屬性區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android實(shí)現(xiàn)本地Service方法控制音樂播放
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)本地Service方法控制音樂播放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Android SharePreferences與數(shù)據(jù)庫SQLite存儲(chǔ)實(shí)現(xiàn)方法介紹
這篇文章主要介紹了Android SharePreferences與數(shù)據(jù)庫SQLite用于存儲(chǔ)的具體實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09
Android進(jìn)程間大數(shù)據(jù)通信LocalSocket詳解
這篇文章主要為大家介紹了Android進(jìn)程間大數(shù)據(jù)通信LocalSocket詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android PickerView實(shí)現(xiàn)三級聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android PickerView實(shí)現(xiàn)三級聯(lián)動(dòng)效果,PickerView實(shí)現(xiàn)全國地址的選擇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Flutter TV Android端開發(fā)技巧詳細(xì)教程
這篇文章主要為大家介紹了Flutter TV Android端開發(fā)技巧詳細(xì)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android開發(fā)中requestfocus()無效的原因及解決辦法
這篇文章主要介紹了Android開發(fā)中requestfocus()無效的原因及解決辦法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08

