網站首頁 編程語言 正文
什么是依賴注入
首先,某個類的成員變量稱為依賴,如若此變量想要實例化引用其類的方法,可以通過構造函數傳參或者通過某個方法獲取對象,此等通過外部方法獲取對象實例的稱為依賴注入;而依賴注入又可以簡單分為手動注入和自動注入兩種方式;Hilt
就是基于Dagger進行場景化優化的一個依賴注入庫,Hilt是Google專門為Android平臺打造的一個依賴注入庫,在使用上極大程度進行啦簡化(與dagger相比)
使用依賴注入的好處
Google文檔中介紹的優勢如下:
- 重用代碼
- 易于重構
- 易于測試
簡單來說,在開發中某些內容需要進行層層手動調用,而且需要手動進行實例化;對于Hilt而言,它可以自動進行依賴注入,并且為項目中的每個 Android 類提供容器并自動管理其生命周期;某些需要全局使用的數據,可以通過Hilt進行共享,從而簡化代碼
Hilt 中常用的預定義限定符
@HiltAndroidApp
所有使用 Hilt 的應用都必須包含一個帶有 @HiltAndroidApp
注解的 Application 類。@HiltAndroidApp
會觸發 Hilt 的代碼生成操作,生成的代碼包括應用的一個基類,該基類充當應用級依賴項容器,記得此Application類要在清單文件中進行引用
@HiltAndroidApp class App : Application() { ... }
@AndroidEntryPoint
如果某個Activity要使用Hilt依賴注入,就必須給Activity添加@AndroidEntryPoint注解,同理Activity中的某個Fragment也需要使用,也必須添加@AndroidEntryPoint注解;
目前Hilt 支持以下 Android 類:
- Application(通過使用 @HiltAndroidApp)
- ViewModel(通過使用 @HiltViewModel)
- Activity
- Fragment
- View
- Service
- BroadcastReceiver
@AndroidEntryPoint class MainActivity : ComponentActivity() {...}
@Module
Hilt帶有一個模塊的類,使用@Module
注解的類,它會告知Hilt,它提供了哪些實例,通常和@Provider
搭配使用,必須通過@InstallIn
注解為其添加作用域
@InstallIn
對于您可以從中執行字段注入的每個 Android 類,都有一個關聯的 Hilt 組件,您可以在 @InstallIn
注解中引用該組件。每個 Hilt 組件負責將其綁定注入相應的 Android 類。
Android 組件 | 默認綁定 |
---|---|
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知道,提供了哪些實例對象,可以使用@Provides
進行注解,以下提供啦一個數據庫實例,并且作用域是全局單例
@Provides @Singleton fun providerAccountBean():AccountBean{ return AccountBean("FranzLiszt","123456") }
@Inject
如果想要使用Hilt自動進行啦依賴注入的對象,可以使用@Inject
注解進行調用;如下,無需進行實例化,它會自動引用providerAccountBean()
提供的對象
@Inject lateinit var bean: AccountBean
@HiltViewModel
通過名稱就可以了解,它需要與ViewModel
類聯合使用,作用于ViewModel上;如下,與@Inject
結合使用,在構造函數引用啦上述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
? ? }
}
建立實體類
data class AccountBean(var username:String,var password:String)
添加Hilt入口
@HiltAndroidApp class APP:Application() {}
提供對象
此處作為用例,只是簡單寫一個測試用例,在函數中可以編寫復雜的程序,并不會影響程序性能,在程序初始化編譯時會耗時一丟丟。一下提供啦單例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 ... }
然后就可以直接進行對象引用
@Composable fun showAccountInfo() { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = bean.username) Spacer(modifier = Modifier.height(20.dp)) Text(text = bean.password) } }
應用與ViewModel中
在ViewModel中使用HiltViewModel
注解,然后就可以使用Inject
注解獲取Hilt自動注入依賴的對象
@HiltViewModel class AccountViewModel @Inject constructor(private val bean: AccountBean):ViewModel() {...}
定義兩個具有狀態的成員變量,其中AccountState
是一個數據類,具有text和hint兩個成員變量
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初始化函數中,將Hilt提供的對象的值賦值給VM中的兩個狀態變量
init { _usernameState.value = usernameState.value.copy(text = bean.username) _passwordState.value = passwordState.value.copy(text = bean.password) }
通過外部事件進行對應處理,外部輸入框不斷進行值修改,此處同步給VM中的狀態變量
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的兩個成員變量值,然后與兩個輸入框進行綁定,通過監聽輸入框的onValueChange
方法,當其值不斷修改時,然后調用VM中的onEvent
方法,然后修改VM中的狀態內容,由于輸入框綁定了VM的狀態變量,然后狀態變量值改變后,相對應的UI界面會進行重組
@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)) } ) } }
總結
上述的倆個測例,只是使用Hilt提供的便利的冰山一角;Hilt使用起來很方便,而去可以提高代碼結構,省去不必要的代碼;其中Koin
依賴注入庫也備受好評,雖然我沒有使用過,因為Google推Hilt
,就首先入手啦;在性能上,我看了一些其他文章上介紹,大差不差的,所有根據自己需要進行選擇。
原文鏈接:https://blog.csdn.net/News53231323/article/details/128554310
相關推薦
- 2022-06-29 Python解決非線性規劃中經濟調度問題_python
- 2021-12-06 Ubuntu編譯內核模塊,內容體現系統日志中_Linux
- 2023-11-23 cmake: command not found
- 2022-07-26 golang控制goroutine數量以及獲取處理結果
- 2022-11-17 有意思的數據結構默克樹?Merkle?tree應用介紹_其它綜合
- 2022-12-14 React?Native設備信息查看調試詳解_React
- 2022-08-14 Hyper-V設置虛擬機固定Ip的方法步驟_Hyper-V
- 2022-12-22 使用PyCharm調試程序實現過程_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支