一、介紹
Hilt 提供了一種將Dagger依賴注入合并到Android應(yīng)用程序中的標(biāo)準(zhǔn)方法。
說(shuō)白了,他就是針對(duì)android平臺(tái)對(duì)Dagger進(jìn)行了封裝與擴(kuò)展,并提供了android平臺(tái)特有的一些Component ,Scope等,內(nèi)置了預(yù)定義綁定、預(yù)定義限定符等。
支持Android的類有:
Activity、Application、Fragment、View、Service、BroadcastReceiver
二、基本使用
1、核心注解說(shuō)明
1) @HiltAndroidApp注解
所有使用Hilt的應(yīng)用程序都必須要包含一個(gè)使用@HiltAndroidApp注解的appliaction。
因?yàn)樵谏纱a時(shí),需要訪問(wèn)所有的module ,編譯Application類還需要將所有Dagger模塊包含在其傳遞的依賴項(xiàng)中。其他組件可以訪問(wèn)它提供的所有的依賴項(xiàng)。
@HiltAndroidApp注解是用來(lái)生成Hilt Application的,如果使用了Hilt 的Gradle Plugin,那么他的參數(shù)value 就可以不指明,默認(rèn)就是當(dāng)前類的父類;如果沒(méi)有使用插件,那么就需要指明value的類型。
2) @AndroidEntryPoint注解
該注解是表明你的依賴注入注入的位置。該注解目前僅支持在Activity、Fragment、View、Service、BroadcastReceiver中。
ViewModel的注入使用@HiltViewModel.
如果對(duì)Fragment使用依賴注入點(diǎn),那么他所在的Activity也必須添加該注解。
注意:
hilt僅支持?jǐn)U展ComponentActivity的Activity;
Hilt只支持AndroidX下的Fragment;不支持保留的Fragment;
3) @InstallIn注解
該注解表明了當(dāng)前的Module安裝在哪個(gè)Component上,在使用Dagger時(shí),在每一個(gè)Module上需要加上@Module注解,而在Hilt中是使用@Module和@InstallIn注解;這其實(shí)就是Dagger中的一個(gè)標(biāo)準(zhǔn)的Module。
使用了@InstallIn注解的modules ,當(dāng)Component生成后,就會(huì)被安裝到關(guān)聯(lián)的Component或SubComponent上去;
通過(guò)給@InstallIn傳遞參數(shù),來(lái)指定該模塊安裝到哪一個(gè)Component中去;
4) @Singleton注解
Hilt中的@Singleton注解必須要和ApplicationComponent組件一起使用,不能單獨(dú)使用。
5) @Binds注入接口實(shí)例
將接口與實(shí)現(xiàn)類綁定。例如:當(dāng)構(gòu)造方法需要傳遞一個(gè)接口類型的實(shí)例對(duì)象時(shí),就需要使用Binds注解來(lái)注入。
@Binds注解使用的類必須是abstract類
@Binds注解的方法必須是abstract抽象方法,其參數(shù)必須是接口的實(shí)例對(duì)象,返回值必須是接口類
6) @Provides注入實(shí)例
在module中提供的實(shí)例,不能直接通過(guò)構(gòu)造函數(shù)來(lái)提供時(shí)(例如使用第三方的構(gòu)建模式創(chuàng)建等),這時(shí)候就可以@Providers注解來(lái)注釋一個(gè)方法專門提個(gè)這個(gè)對(duì)象實(shí)例來(lái)完成注入。
該方法的返回值必須是需要的對(duì)象的實(shí)例類型;
7) @Qualifier 限定符
當(dāng)你想要Inject的兩個(gè)對(duì)象實(shí)例的類型是一樣的,但是他們又是不同的實(shí)例,就可以使用Qualifier限定兩個(gè)自定義的注解來(lái)完成.
自定義Qualifier的注解
在module的提供實(shí)例的方式上使用自定義的Qualifier注解
在Inject的地方使用Qualifier注解來(lái)進(jìn)行區(qū)分;
@Qualifier
@kotlin.annotation.Retention(AnnotationRetention.BINARY)
annotation class Binder
@Qualifier
@kotlin.annotation.Retention(AnnotationRetention.BINARY)
annotation class Customer
個(gè)人理解,和Dagger中的Named注解類似。
2、Hilt組件的生命周期
Hilt內(nèi)置的android組件的生命周期如下表格所示,可以看出這些Component組件是隨著對(duì)應(yīng)的Android類的生命周期的創(chuàng)建和銷毀而變化,所以我們不需要手動(dòng)去管理這些組件的生命周期。
| 生成的組件 | 創(chuàng)建時(shí)機(jī) | 銷毀時(shí)機(jī) |
|---|---|---|
| ApplicationComponent | Application#onCreate() | Application#onDestroy() |
| ActivityRetainedComponent | Activity#onCreate() | Activity#onDestroy() |
| ActivityComponent | Activity#onCreate() | Activity#onDestroy() |
| FragmentComponent | Fragment#onAttach() | Fragment#onDestroy() |
| ViewComponent | View#super() | 視圖銷毀時(shí) |
| ViewWithFragmentComponent | View#super() | 視圖銷毀時(shí) |
| ServiceComponent | Service#onCreate() | Service#onDestroy() |
3、組件的作用域
默認(rèn)情況下,Hilt中的所有綁定都未限制作用域。這就是說(shuō):每當(dāng)應(yīng)用請(qǐng)求綁定的時(shí)候,都會(huì)創(chuàng)建所需要的類型的一個(gè)實(shí)例。
Hilt允許將綁定的作用域限定為特定組件。Hilt為在同一個(gè)作用域限定范圍內(nèi)的組件創(chuàng)建一次實(shí)例,這樣應(yīng)用的綁定請(qǐng)求共享同一實(shí)例。
下面看看生成組件的作用域:
| Android 類 | 生成的組件 | 作用域 |
|---|---|---|
| Application | ApplicationComponent | @Singleton |
| View Model | ActivityRetainedComponent | @ActivityRetainedScope |
| Activity | ActivityComponent | @ActivityScoped |
| Fragment | FragmentComponent | @FragmentScoped |
| View | ViewComponent | @ViewScoped |
帶有 @WithFragmentBindings 注釋的 View
|
ViewWithFragmentComponent | @ViewScoped |
| Service | ServiceComponent | @ServiceScoped |
作用域直接作用在對(duì)應(yīng)的類上面就可以了。
4、使用步驟
1)添加依賴
從下面的依賴可以看到使用了annotationProcessor注解處理器,說(shuō)明Hilt中使用了APT技術(shù)
//hilt 依賴
implementation 'com.google.dagger:hilt-android:2.38.1'
annotationProcessor 'com.google.dagger:hilt-compiler:2.38.1'
2)添加插件
Hilt 插件是為了更好的使用Hilt API ,提供的一個(gè)字節(jié)碼轉(zhuǎn)換器,可想而知這其中使用了字節(jié)碼插樁技術(shù)。
//工程的build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
}
}
//模塊module的build.gradle 添加應(yīng)用插件
plugins {
id 'dagger.hilt.android.plugin'
id 'kotlin-kapt'
}
3)Hilt入口:自定義application
每一個(gè)使用了Hilt的app都必須使用@HiltAndroidApp注解了的自定義application ,這里是生成代碼的入口位置,方便訪問(wèn)所有使用了Dagger的module.
@HiltAndroidApp
class CustomApplication : Application() {
override fun onCreate() {
super.onCreate()
//這里可以處理一些全局的Component等
}
}
4)創(chuàng)建一個(gè)Module
@InstallIn(ActivityComponent::class) 這個(gè)安裝注解,我們需要特別注意一下:
1、他的參數(shù)必須是使用@DefineComponent注解的Component ;
下面是筆者傳遞了MainActivity 參數(shù)后編譯出現(xiàn)的錯(cuò)誤,MainActivity里面是需要Inject 該Module的
@InstallIn, can only be used with @DefineComponent-annotated classes, but found: [com.leon.study_jetpack_hilt.MainActivity]2、必須通過(guò)參數(shù)指明是在哪個(gè)Component上,不可不傳參數(shù);
下面是不傳遞參數(shù),報(bào)錯(cuò)的異常錯(cuò)誤:
Execution failed for task ':app:kaptDebugKotlin'. > A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution > java.lang.reflect.InvocationTargetException (no error message)
@Module
@InstallIn(ActivityComponent::class)
class HttpResponseModule {
@Provides
fun getHttpModule(): HttpResponseModule {
return HttpResponseModule()
}
}
5)添加注入點(diǎn)、Inject Modules
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mHttpResponseModule:HttpResponseModule
@Inject
lateinit var mHttpResponseModule2:HttpResponseModule
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
println("HttpResponseModule object that via inject of hilt: hashcode = "+mHttpResponseModule.hashCode())
println("HttpResponseModule object that via inject of hilt: hashcode = "+mHttpResponseModule2.hashCode())
}
}
/*
* 輸出的結(jié)果:
2021-08-06 14:33:39.641 27582-27582/com.leon.study_jetpack_hilt I/System.out: HttpResponseModule object that via inject of hilt: hashcode = 26182251
2021-08-06 14:33:39.641 27582-27582/com.leon.study_jetpack_hilt I/System.out: HttpResponseModule object that via inject of hilt: hashcode = 228151752
*/
5、接口實(shí)例注入
接口沒(méi)有辦法直接構(gòu)造對(duì)象,那么就需要一個(gè)帶有@Binds注解的抽象方法的Module來(lái)告知,該抽象方法的參數(shù)會(huì)告訴Hilt創(chuàng)建的實(shí)例的類型,而返回值的類型則告知是返回的哪個(gè)接口的實(shí)例。
下面的java代碼是成功的:
//定義接口
public interface IBook {
}
//接口的實(shí)現(xiàn)類
public class KotlinBook implements IBook{
@Inject
KotlinBook(){
}
}
//定義module
@Module
@InstallIn(ActivityComponent.class)
public abstract class BookModule {//這里注意是抽象類
@Binds
abstract IBook getBooks(KotlinBook book);//這里需要特別注意參數(shù)和返回值,方法是抽象方法
}
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
@Inject
IBook book;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate: "+book.hashCode());
}
}
kotlin代碼:一直無(wú)法inject成功:
interface Book {
}
class JavaBook @Inject constructor() : Book {
}
/**
* 模塊必須是抽象類
*/
@Module
@InstallIn(ActivityComponent::class)
abstract class BookModule{
//抽象函數(shù)
@Binds
abstract fun getBook(book: JavaBook): Book
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var book: Book
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
println("HttpResponseModule object that via inject of hilt: listener----hashcode = " + book.hashCode())
}
}
三、原理及生成源碼分析
Hilt的核心還是Dagger的原理來(lái)完成,他是在Dagger的基礎(chǔ)上去掉了Component組件,而在編譯的時(shí)候會(huì)根據(jù)@InstallIn注解來(lái)自動(dòng)生成Component,并把他們注入到相關(guān)的代碼中,這樣就可以全身心的只關(guān)注對(duì)象的創(chuàng)建和要把這些對(duì)象注入的位置。
Hilt內(nèi)置了針對(duì)Android類的一些Component組件,但是對(duì)于我們自己使用的是非Android內(nèi)置類的時(shí)候,還是和Dagger的使用一樣來(lái)做。
先來(lái)找找編譯后生成的文件:

1) Inject 流程
-
Hilt_MainActivity.java源碼:AndroidEntryPoint 該注解生成的class文件
/** * A generated base class to be extended by the @dagger.hilt.android.AndroidEntryPoint annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation. */ public abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManagerHolder { private volatile ActivityComponentManager componentManager; //這個(gè)方法調(diào)用了injectMainActivity() protected void inject() { if (!injected) { injected = true; ((MainActivity_GeneratedInjector) this.generatedComponent()).injectMainActivity(UnsafeCasts.<MainActivity>unsafeCast(this)); } } }
-
MainActivity_GeneratedInjector.java源碼:
其實(shí)就是我們自己寫的Component,只不過(guò)不需要我們寫,而是編譯期幫我們生成了。
@GeneratedEntryPoint @InstallIn(ActivityComponent.class) public interface MainActivity_GeneratedInjector { void injectMainActivity(MainActivity mainActivity); }
-
MainActivity_GeneratedInjector 這個(gè)接口的實(shí)現(xiàn)在CustomApplication_HiltComponents.java文件中的一個(gè)靜態(tài)抽象類:
@ActivityScoped public abstract static class ActivityC implements MainActivity_GeneratedInjector, ActivityComponent, DefaultViewModelFactories.ActivityEntryPoint, HiltWrapper_HiltViewModelFactory_ActivityCreatorEntryPoint, FragmentComponentManager.FragmentComponentBuilderEntryPoint, ViewComponentManager.ViewComponentBuilderEntryPoint, GeneratedComponent { @Subcomponent.Builder abstract interface Builder extends ActivityComponentBuilder { } }
-
在DaggerCustomApplication_HiltComponents_SingletonC.java文件中看看ActvityC的實(shí)例類:activityCImpl
private static final class ActivityCImpl extends CustomApplication_HiltComponents.ActivityC { private final HttpResponseModule httpResponseModule; //這個(gè)我們?cè)谧?cè)流程里面來(lái)看 private final DaggerCustomApplication_HiltComponents_SingletonC singletonC; private ActivityCImpl(DaggerCustomApplication_HiltComponents_SingletonC singletonC, ActivityRetainedCImpl activityRetainedCImpl, HttpResponseModule httpResponseModuleParam, Activity activityParam) { this.singletonC = singletonC; this.activityRetainedCImpl = activityRetainedCImpl; this.httpResponseModule = httpResponseModuleParam; } @Override public void injectMainActivity(MainActivity mainActivity) { injectMainActivity2(mainActivity); } private MainActivity injectMainActivity2(MainActivity instance) { MainActivity_MembersInjector.injectMHttpResponseModule(instance, HttpResponseModule_GetHttpModuleFactory.getHttpModule(httpResponseModule)); MainActivity_MembersInjector.injectMHttpResponseModule2(instance, HttpResponseModule_GetHttpModuleFactory.getHttpModule(httpResponseModule)); return instance; } }
-
繼續(xù)進(jìn)入MainActivity_MembersInjector.java文件:
看到這個(gè)文件就都明了了,這就是Dagger里面Inject生成的代碼。
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> { private final Provider<HttpResponseModule> mHttpResponseModuleProvider; private final Provider<HttpResponseModule> mHttpResponseModule2Provider; public MainActivity_MembersInjector(Provider<HttpResponseModule> mHttpResponseModuleProvider, Provider<HttpResponseModule> mHttpResponseModule2Provider) { this.mHttpResponseModuleProvider = mHttpResponseModuleProvider; this.mHttpResponseModule2Provider = mHttpResponseModule2Provider; } public static MembersInjector<MainActivity> create( Provider<HttpResponseModule> mHttpResponseModuleProvider, Provider<HttpResponseModule> mHttpResponseModule2Provider) { return new MainActivity_MembersInjector(mHttpResponseModuleProvider, mHttpResponseModule2Provider); } @Override public void injectMembers(MainActivity instance) { injectMHttpResponseModule(instance, mHttpResponseModuleProvider.get()); injectMHttpResponseModule2(instance, mHttpResponseModule2Provider.get()); } @InjectedFieldSignature("com.leon.study_jetpack_hilt.MainActivity.mHttpResponseModule") public static void injectMHttpResponseModule(MainActivity instance, HttpResponseModule mHttpResponseModule) { instance.mHttpResponseModule = mHttpResponseModule; } @InjectedFieldSignature("com.leon.study_jetpack_hilt.MainActivity.mHttpResponseModule2") public static void injectMHttpResponseModule2(MainActivity instance, HttpResponseModule mHttpResponseModule2) { instance.mHttpResponseModule2 = mHttpResponseModule2; } }
2) 注冊(cè)流程
-
Hilt_CustomApplication.java
這里主要就是創(chuàng)建了一個(gè)DaggerCustomApplication_HiltComponents_SingletonC 的實(shí)例,并與當(dāng)前app的應(yīng)用上下文綁定;
public abstract class Hilt_CustomApplication extends Application implements GeneratedComponentManagerHolder { private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() { @Override public Object get() { return DaggerCustomApplication_HiltComponents_SingletonC.builder() .applicationContextModule(new ApplicationContextModule(Hilt_CustomApplication.this)) .build(); } }); } //ApplicationContextModule 類的實(shí)現(xiàn) @Module @InstallIn(SingletonComponent.class) public final class ApplicationContextModule { private final Context applicationContext; public ApplicationContextModule(Context applicationContext) { this.applicationContext = applicationContext; } @Provides @ApplicationContext Context provideContext() { return applicationContext; } @Provides Application provideApplication() { return Contexts.getApplication(applicationContext); } }
-
DaggerCustomApplication_HiltComponents_SingletonC .java
先來(lái)看看該類的結(jié)構(gòu):大量的靜態(tài)內(nèi)部類

其實(shí)就是將app的上下文保存下來(lái),并創(chuàng)建了自己的實(shí)例:
public final class DaggerCustomApplication_HiltComponents_SingletonC extends CustomApplication_HiltComponents.SingletonC {
private final ApplicationContextModule applicationContextModule;
private final DaggerCustomApplication_HiltComponents_SingletonC singletonC = this;
private DaggerCustomApplication_HiltComponents_SingletonC(
ApplicationContextModule applicationContextModuleParam) {
this.applicationContextModule = applicationContextModuleParam;
}
public static Builder builder() {
return new Builder();
}
@Override
public void injectCustomApplication(CustomApplication customApplication) {
}
@Override
public ActivityRetainedComponentBuilder retainedComponentBuilder() {
return new ActivityRetainedCBuilder(singletonC);
}
@Override
public ServiceComponentBuilder serviceComponentBuilder() {
return new ServiceCBuilder(singletonC);
}
//靜態(tài)內(nèi)部類,來(lái)創(chuàng)建DaggerCustomApplication_HiltComponents_SingletonC的實(shí)例
public static final class Builder {
private ApplicationContextModule applicationContextModule;
private Builder() {
}
public Builder applicationContextModule(ApplicationContextModule applicationContextModule) {
this.applicationContextModule = Preconditions.checkNotNull(applicationContextModule);
return this;
}
public CustomApplication_HiltComponents.SingletonC build() {
Preconditions.checkBuilderRequirement(applicationContextModule, ApplicationContextModule.class);
return new DaggerCustomApplication_HiltComponents_SingletonC(applicationContextModule);
}
}
}
-
ActivityRetainedBuilder 這個(gè)類實(shí)現(xiàn),其實(shí)就是創(chuàng)了ActivityRetainedCImpl的實(shí)例對(duì)象