Android Hilt的使用以及遇到的問題
簡(jiǎn)介
Hilt 提供了一種將Dagger 依賴注入到Android 應(yīng)用程序的標(biāo)準(zhǔn)方法。為Android 應(yīng)用程序簡(jiǎn)化提供一組標(biāo)準(zhǔn)的、簡(jiǎn)化設(shè)置、可以讀的組件;且為不同類型的構(gòu)建(例如:測(cè)試、調(diào)試、發(fā)行)提供一種簡(jiǎn)單的方法。
可以理解為Google 為了統(tǒng)一依賴注入組件,但是Dagger 用起來比較復(fù)雜。就針對(duì)Android開發(fā)了一套適配庫。
導(dǎo)入Hilt
apply plugin: 'com.android.application'
apply plugin: 'dagger.hilt.android.plugin'
android {
// ...
}
dependencies {
implementation 'com.google.dagger:hilt-android:2.34.1-beta'
kapt 'com.google.dagger:hilt-compiler:2.34.1-beta'
// For instrumentation tests
androidTestImplementation 'com.google.dagger:hilt-android-testing:2.34.1-beta'
kaptAndroidTest 'com.google.dagger:hilt-compiler:2.34.1-beta'
// For local unit tests
testImplementation 'com.google.dagger:hilt-android-testing:2.34.1-beta'
kaptTest 'com.google.dagger:hilt-compiler:2.34.1-beta'
}
kapt {
correctErrorTypes true
}
設(shè)置correctErrorTypes 為true ,將kapt配置為更正錯(cuò)誤類型 。
這里遇到一個(gè)問題,當(dāng)我的gradle 版本為 3.4.1 的時(shí)候
classpath 'com.android.tools.build:gradle:3.4.1'
apply plugin: 'dagger.hilt.android.plugin'插件一直安裝失敗,
提示找不到 "com/android/Version" 把gradle 改成 4.1.2 就沒問題了
且注意 如果你是多module的項(xiàng)目,
apply plugin: 'dagger.hilt.android.plugin' 一定要plugin在主module下
(也就是跟 apply plugin: 'com.android.application' 一起),
若是只在子module下,主module的注入不會(huì)被實(shí)現(xiàn)。(問題1,后面會(huì)解釋問題原因)
buildscript {
repositories {
// other repositories...
mavenCentral()
}
dependencies {
// other plugins...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.34.1-beta'
}
}
組件層次
Hilt把Dagger 手動(dòng)創(chuàng)建Component 改成了預(yù)定義的Component,且自動(dòng)集成到Android應(yīng)用程序的各個(gè)生命周期中。通過注解的方式@InstallIn(xxxComponent.class)進(jìn)行綁定。
下圖顯示了標(biāo)準(zhǔn)的Hilt組件層次結(jié)構(gòu)。每個(gè)組件上方的注釋是作用域注釋,用于將綁定范圍限制為該組件的生存期。組件下方的箭頭指向任何子組件。通常,子組件中的綁定可以依賴于祖先組件中的任何綁定。

組件默認(rèn)綁定
每個(gè)Hilt 組件都帶有一組默認(rèn)綁定,這些默認(rèn)綁定可以作為依賴注入到你自定義綁定中
| Component | Default Bindings |
|---|---|
| SingletonComponent | Application |
| ActivityRetainedComponent | Application |
| ViewModelComponent | SavedStateHandle |
| ActivityComponent | Application, Acitvity |
| FragmentComponent | Application, Acitvity, Fragment |
| ViewComponent | Application, Acitvity, View |
| ViewWithFragmentComponent | Application, Acitvity, Fragment, View |
| ServiceComponent | Application, Service |
簡(jiǎn)單使用
下面我為大家介紹以下一些注解的使用:
- @HiltAndroidApp
- @AndroidEntryPoint
- @InstallIn
- @Module
- @Provides
- @Binds
- @HiltViewModel
- @EntryPoint
想要了解更多的建議直接查看官方文檔
@HiltAndroidApp
介紹
所有使用Hilt的App 必須包含一個(gè)被@HiltAndroidApp 注釋的Appliction 類。
@HiltAndroidApp 會(huì)生成一個(gè)Hilt_MyApplication 的基類,并且繼承與@HiltAndroidApp 注釋的類的基類,然后將@HiltAndroidApp 注釋的類的基類替換成Hilt_MyApplication。例如:
這是我們應(yīng)用的 MyApplication
@HiltAndroidApp
class MyApplication extends BaseApplication{
}
使用@HiltAndroidApp Hilt 將會(huì)生成 Hilt_MyApplication
public abstract class Hilt_MyApplication extends BaseApplication implements GeneratedComponentManagerHolder {
private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
@Override
public Object get() {
return DaggerMyApplication_HiltComponents_SingletonC.builder()
.applicationContextModule(new ApplicationContextModule(Hilt_MyApplication.this))
.build();
}
});
@Override
public final ApplicationComponentManager componentManager() {
return componentManager;
}
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
@CallSuper
@Override
public void onCreate() {
// This is a known unsafe cast, but is safe in the only correct use case:
// MyApplication extends Hilt_MyApplication
((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.<MyApplication>unsafeCast(this));
super.onCreate();
}
}
并且使我們的 MyApplication 繼承 Hilt_MyApplication,通過這種方式將modules 注入到我們的應(yīng)用中。
可以看到具體的注入方法就是Hilt_MyApplication onCreate() 函數(shù)中的
((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.unsafeCast(this));
這句代碼,generatedComponent() 返回的是 MyApplication_HiltComponents.SingletonC 對(duì)象,這個(gè)對(duì)象中就是我們所有module 的代碼實(shí)現(xiàn)。有興趣的同學(xué)可以自己去看一下,我這里就不貼代碼了
使用
使用分為兩種情況,添加和沒有添加 Hilt Gradle插件
//沒有添加插件
@HiltAndroidApp(BaseApplication.class)
class MyApplication extends Hilt_MyApplication{}
//添加插件
@HiltAndroidApp
class MyApplication extends BaseApplication{}
建議添加插件,使用起來會(huì)更簡(jiǎn)單。本文以下的示例都假定以使用插件。
這里需要注意的是如果要在MyApplication 中使用注入的對(duì)象,需要在 super.onCreate() 之后才能使用。 原因且看介紹中的 Hilt_MyApplication 源碼。
這里解釋一下問題1出現(xiàn)的原因,是因?yàn)槲覜]有添加插件但@HiltAndroidApp 使用的時(shí)候用的卻是添加了插件的用法。所以會(huì)出現(xiàn)module 注入不被實(shí)現(xiàn)的情況。
@AndroidEntryPoint
介紹
安卓成員注入,使用@AndroidEntryPoint 注解后就可以在該類中使用module注入的成員變量。但@AndroidEntryPoint 有類型限制,只能在以下的類上使用:
- Activity
- Fragment
- View
- Service
- BroadcastReceiver
使用
@AndroidEntryPoint
public final class MyActivity extends MyBaseActivity {
// Bindings in SingletonComponent or ActivityComponent
@Inject Bar bar;
@Override
public void onCreate(Bundle savedInstanceState) {
// Injection happens in super.onCreate().
super.onCreate();
// Do something with bar ...
}
}
同樣要注意是是需要在 super.onCreate() 后使用注入的成員變量
@Module 和 @InstallIn
介紹
@Module 跟Dagger 里的是同一個(gè),沒什么好說的。
@InstallIn 通過使用@InstallIn(xxxComponent.class) 將module 安裝到指定的組件中,在Hilt 中所以module 都必須添加這個(gè)注釋,如果組件中就找不到這個(gè)module ,可能引起編譯錯(cuò)誤。
當(dāng)然一個(gè)module 也可安裝到多個(gè)組件上如:@InstallIn({ViewComponent.class, ViewWithFragmentComponent.class})
使用
@Module
@InstallIn(SingletonComponent.class)
public final class FooModule {
// @InstallIn(SingletonComponent.class) module providers have access to
// the Application binding.
@Provides
static Bar provideBar(Application app) {...}
}
每個(gè)組件都帶有作用域注釋,該注釋可用于記住對(duì)組件生存期的綁定。例如,要將范圍綁定到 SingletonComponent組件,請(qǐng)使用@Singleton批注:
@Module
@InstallIn(SingletonComponent.class)
public final class FooModule {
// @Singleton providers are only called once per SingletonComponent instance.
@Provides
@Singleton
static Bar provideBar() {...}
}
此外,每個(gè)組件都有默認(rèn)情況下可用的綁定。例如,該SingletonComponent組件提供了Application 綁定:
@Module
@InstallIn(SingletonComponent.class)
public final class FooModule {
// @InstallIn(SingletonComponent.class) module providers have access to
// the Application binding.
@Provides
static Bar provideBar(Application app) {...}
}
@Provides 和 @Binds
介紹
@Provides 注釋Module 中的方法以創(chuàng)建提供者方法綁定。該方法的返回類型綁定到其返回值。
@Binds 注釋Module 中的抽象方法,一般方法的返回是一個(gè)接口,參數(shù)是實(shí)現(xiàn)接口的子類,在調(diào)用是會(huì)調(diào)用參數(shù)的子類中的方法實(shí)現(xiàn)。
使用
@Module
@InstallIn(SingletonComponent.class)
public final class FooModule {
@Provides
@Singleton
static Bar provideBar() {...}
}
@Module
@InstallIn(SingletonComponent.class)
public abstract class BindModule {
@Binds
@Singleton
abstract Random bindRandom(SecureRandom secureRandom);
}
@HiltViewModel
介紹
使用 @HiltViewModel 注釋ViewModel,ViewModel 在創(chuàng)建的時(shí)候就會(huì)走Hilt 創(chuàng)建的HiltViewModelFactory 進(jìn)行創(chuàng)建。就可以使用在創(chuàng)建的時(shí)候使用Module 中提供的實(shí)例
使用
@HiltViewModel
public final class FooViewModel extends ViewModel {
@Inject
FooViewModel(SavedStateHandle handle, Foo foo) {
// ...
}
}
然后就可以在帶有@AndroidEntryPoint 注解的activity、fragment 中使用了
@AndroidEntryPoint
public final class MyActivity extends AppCompatActivity {
private FooViewModel fooViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fooViewModel = new ViewModelProvider(this).get(FooViewModel.class);
}
}
@EntryPoint
介紹
為不能使用注解的地方提供注入的對(duì)象。因?yàn)锧AndroidEntryPoint 使用范圍有限,在這范圍之外要使用Hilt 注入的實(shí)例就可以使用@EntryPoint 來實(shí)現(xiàn)。
這個(gè)像是Hilt 把Component標(biāo)準(zhǔn)化后,使用者不能再里面添加方法,導(dǎo)致不能為使用不了注解的地方提供依賴而做出的解決方案。
@EntryPoint
@InstallIn(SingletonComponent.class)
public interface FooBarInterface {
Bar getBar();
}
如果使用上面的定義
Bar bar = EntryPoints.get(applicationContext, FooBarInterface.class).getBar();
小結(jié)
一開始使用的時(shí)候我看到是 安卓開發(fā)平臺(tái)“Hilt 和 Jetpack 集成”這個(gè)文檔,真坑,文檔不及時(shí)更新也不把官方鏈接放一下。吐槽一下。然后幾經(jīng)周轉(zhuǎn)找到了官方文檔才能有幸為大家介紹一下Hilt。
使用起來確實(shí)要比Dagger 舒服的多,少了很多模板代碼,范圍和生命周期的綁定也更好理解。不多bb 學(xué)它
以上就是Android Hilt的使用以及遇到的問題的詳細(xì)內(nèi)容,更多關(guān)于Android Hilt的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android adb.exe程序啟動(dòng)不起來 具體解決方法
這篇文章主要介紹了Android adb.exe程序啟動(dòng)不起來 具體解決方法,有需要的朋友可以參考一下2013-12-12
Flutter實(shí)現(xiàn)滑動(dòng)塊驗(yàn)證碼功能
這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)滑動(dòng)塊驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Android GridView簡(jiǎn)單實(shí)例
這篇文章主要為大家詳細(xì)介紹了Android GridView簡(jiǎn)單實(shí)例,簡(jiǎn)單實(shí)現(xiàn)九宮格效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android Studio 中的Gradle構(gòu)建系統(tǒng)示例
這篇文章主要介紹了Android Studio 中的Gradle構(gòu)建系統(tǒng)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11

