該章站在企業項目角度上如何在MVVM框架上完善並且合理的使用Hilt。
所以如果沒了解MVVM的結構建議可以直接忽略這章。大家知道,MVVM裏面View和Model之間有關聯,假設一個場景View觸發一個點擊事件調用Model查詢,然後Model會調用相關Http類進行查詢,返回數據給Model,Model再返回數據給View。
當然上述表達的不是嚴格意義的MVVM,但是流程相仿,主要是講解如何註解Model和相關Http類,讓他們自動生成
讓我們先看看有哪些類
類名 | 解釋 |
---|---|
MyApplication | app的入口 |
MainActivity | 顧名思義就是展示的View |
ViewModel | MainActivity對應的ViewModel,也是MVVM中的Model |
TestApi | 一個仿造Http的類,只是單純返回一個數據 |
NetworkModule | 一個製造類,Hilt通過標記自動尋找相關類,然後會找到該類調用相關函數實例化TestApi |
那麼讓我們直接快速講解
1. 在Project的build.gradle添加引入
dependencies {
...
classpath "com.google.dagger:hilt-android-gradle-plugin:2.36"
}
2. 在module的build.gradle分別兩處地方添加
plugins {
...
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
……
implementation "com.google.dagger:hilt-android:2.37"
kapt "com.google.dagger:hilt-android-compiler:2.37"
}
好了!添加相關插件自動下載後,我們繼續!
3. HiltAndroidApp標記Application
@HiltAndroidApp
class MyApplication : Application()
跟dagger有點不一樣的是,必須包含一個帶有 @HiltAndroidApp標記的Application類。
當然,別忘記修改AndroidManifest.xml
<application
android:allowBackup="true"
android:name=".MyApplication"
...
</application>
5. Activity
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: ViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tvName.append(viewModel.shopBanner.toString())
}
}
大家看到viewModel就很奇怪,沒有標記就能自動生成使用了?其實by viewModels()
就已經代表Hilt生成處理了。讓我們往下看
4. 創建一個仿造訪問網絡數據的TestApi 類
class TestApi {
fun getValue(): Int {
return 1
}
}
只是一個簡單的創建返回數據類
5. ViewModel
可以同時看到兩個標記@HiltViewModel
和 @Inject
,那麼TestApi在哪裏實例化呢?Activity也沒有創建TestApi呀,這就是Hilt方便的地方,讓我們看下一個NetworkModule
@HiltViewModel
class ViewModel @Inject constructor(
testApi: TestApi
) : ViewModel() {
val shopBanner = testApi.getValue()
}
6. NetworkModule
通過@Module
、@InstallIn
、@Provides
、@Singleton
等多個標記,讓Hilt尋找TestApi的構造方法的時候,找到這裏,並且調用GetApi方法創建實例。
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun GetApi(): TestApi {
return TestApi()
}
}
7. End
基本就結束了,那麼大家很奇怪,其實很簡單兩句話代碼放在MainActivity直接實例化不就行了嗎,其實不是這樣的,當項目越龐大的時候,可能改變構造函數的時候,那麼我們使用Hilt就能很方便的集中在類似NetworkModule
這樣的類處理,而在Activity這些類中,我們是不需要關心構造函數的。如果你覺得理解還抽象,那麼建議先用平常方式寫Mvvm,最後再用Hilt優化這方面,或許會有更深入的理解呢!
標記符講解表格
標記符 | 標記是爲了什麼 |
---|---|
@Module | 標記一個module,代表提供一些無法用構造@Inject的依賴, 比如接口, 第三方庫類型, Builder模式構造的對象等 |
@InstallIn | 委託Hilt幫我們管理範圍,以管理對象的生命週期,通過指定 Hilt 組件告訴 Hilt 綁定在哪些容器中可用,有很多種容器具體可以看圖1 |
@Provides | 提供實例,註釋函數,以告訴 Hilt 如何提供無法注入構造函數的 類型 |
@ViewModelScoped | 當在ViewModel中引入協程,如果直接使用CoroutineScope,那麼需要在onCleared()方法中取消協程,如果忘記取消協程那麼會導致出現內存泄漏等各種問題,此時需要使用ViewModel擴展屬性viewModelScope來實現協程作用域 |
作用域
只是簡單介紹依賴注入使用方式的實例源碼如下:
zhongjhATC/HiltAndDaggerDemo: 演示 Hilt、Dagger 的demo (github.com)
其他相關文章
1. 【淺入深出理解 dagger、Hilt】 - 簡介 - 簡書 (jianshu.com)
2. 【淺入深出理解 dagger、Hilt】 - dagger無參依賴注入 - 簡書 (jianshu.com)
3. 【淺入深出理解 dagger、Hilt】 - dagger有參依賴注入 - 簡書 (jianshu.com)
4. 【淺入深出理解 dagger、Hilt】 - Hilt - 簡書 (jianshu.com)
在 Android 應用中使用 Hilt | Google Developers