Hilt是Google根据Dagger2开发的专用于Android的依靠注入结构,比较Dagger,它的优势如下:
- 简化了Android运用中Dagger相根底架构。
- 创立了一组标准的组件和效果域,以简化设置、提高可读性以及在运用之间共享代码。
- 供给了一种简略的办法来为各种构建类型(如测验、调试或发布)装备不同的绑定。
引入依靠
-
在项目根级
build.gradle中增加hilt-android-gradle-plugin插件。buildscript { dependencies { classpath 'com.google.dagger:hilt-android-gradle-plugin:x.y.z' } } -
在模块级
build.gradle中运用插件和导入依靠。plugins { id 'kotlin-kapt' id 'dagger.hilt.android.plugin' } android { ... // hilt需求敞开Java8 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { implementation "com.google.dagger:hilt-android:2.38.1" kapt "com.google.dagger:hilt-compiler:2.38.1" }
运用
Hilt是在Dagger2的根底上进行开发的,其本质还是对Dagger的运用进行简化。比较dagger- android,Hilt会协助咱们主动生成更多的模板代码,然后让运用过程更加简洁。但不管怎样精简,其Dagger的底层完成还是不变的,因此,了解Dagger将协助咱们更好的掌握Hilt,关于Dagger的介绍拜见Dagger 系列文章。
界说运用类
运用Hilt需求为运用的Application类增加@HiltAndroidApp注解,运用了此注解后,Hilt将会运用gradle plugin为MyApplication生成一个名为Hilt_Application的父类(gradle插件会主动调整MyApplication的继承)以及运用等级的Component。
@HiltAndroidApp
class MyApplication : Application() {
...
}
在Hilt_Application中包含着对运用等级Component的初始化代码以及对Application的注入代码:
public abstract class Hilt_MyApplication
extends Application
implements GeneratedComponentManagerHolder
{
private final ApplicationComponentManager componentManager =
new ApplicationComponentManager(new ComponentSupplier() {
@Override
public Object get() {
// 运用等级的Component的初始化
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() {
// 注入
((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.<MyApplication>unsafeCast(this));
super.onCreate();
}
}
关于DaggerMyApplication_HiltComponents_SingletonC的内容将在后文剖析。
为Android其它组件注入依靠
Hilt支撑为以下Android组件注入依靠:
ApplicationViewModel-
ComponentActivity(不支撑根底的Activity) -
androidx.Fragment(不支撑根底的Fragment) ViewServiceBroadcastReceiver
要为Android组件注入依靠,需求运用@AndroidEntryPoint注解符号对应的组件类(关于Application类需求运用@HiltAndroidApp,关于ViewModel需求运用@HiltViewModel),获取依靠项则与Dagger相同,运用@Inject注解符号非私有字段即可。
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
@Inject lateinit var analytics: AnalyticsAdapter
...
}
与@HiltAndroidApp相同,Hilt也会为@AndroidEntryPoint和@HiltViewModel符号的组件生成相应的Component和用于完成注入的父类。
绑定(依靠供给)
Hilt中的绑定与Dagger中的界说方式共同。
关于咱们能够操控的依靠类型,直接在结构函数上运用@Inject注解即可。
class Student @Inject constructor() {
...
}
关于无法运用constructor-inject的依靠类型,也能够运用模块供给绑定信息。Hilt的模块和Dagger的模块是相同的,也是运用@Module符号的类。但需求注意的是,在Hilt中需求运用@InstallIn为模块指定要安装到的Component,关于Component的介绍见后文组件 Component 。
@Module
@InstallIn(SingletonComponent::class)
class CommonModule {
...
}
和Dagger相同,在模块中,咱们能够运用@Provides以及@Binds系列的注解来绑定依靠项。
@Module
@InstallIn(SingletonComponent::class)
class CommonModule {
@Provides
fun provideSp(
context: Application
): SharedPreferences {
return context.getSharedPreferences("main", Context.MODE_PRIVATE)
}
@Binds
abstract fun bindAnalyticsService(
analyticsServiceImpl: AnalyticsServiceImpl
): AnalyticsService
...
}
限制符 Qualifier
Hilt中限制符的运用也与Dagger中相同。可是Hilt为Android供给了两个预界说的限制符:@ApplicationContext与@ActivityContext,用来限制注入的context是运用的context还是Activity的context。
组件 Component
运用Hilt时,大部分时分咱们都无需手动界说Component,Hilt会主动的帮咱们生成与Android组件相应的Component。Hilt供给了以下组件的主动生成:
| Android 组件 | Hilt Component |
|---|---|
| Application | SingletonComponent |
| – | ActivityRetainedComponent |
| ViewModel | ViewModelComponent |
| Activity | ActivityComponent |
| Fragment | FragmentComponent |
| View | ViewComponent |
| 运用@WithFragmentBindings符号的View | ViewWithFragmentComponent |
| Service | ServiceComponent |
Hilt不会为
BroadcastReceiver生成组件,BroadcastReceiver直接经过SingletonComponent履行注入。
Hilt也允许你自界说Component,可是大部分时分都不需求它,关于自界说Component能够参考官方文档。
组件的层次结构
Hilt会将生成的Component组织成一定的层次结构,在这个层次结构中,位于下面的组件能够直接运用上层的子组件的依靠项,比方ViewComponent能够运用ActivityComponent中的依靠项;ActivityComponent能够运用SingletonComponent中的依靠项。
组件的生命周期
Hilt会按照对应Android组件类的生命周期主动创立和毁掉生成Component实例。
| Component | 创立机遇 | 毁掉机遇 |
|---|---|---|
| SingletonComponent | Application#onCreate() | Application#已毁掉 |
| ActivityRetainedComponent | Activity#onCreate() | Activity#onDestroy() |
| ViewModelComponent | ViewModel已创立 | ViewModel已毁掉 |
| ActivityComponent | Activity#onCreate() | Activity#onDestroy() |
| FragmentComponent | Fragment#attach() | Fragment#onDestroy() |
| ViewComponent | View#super() | View已毁掉 |
| ViewWithFragmentComponent | View#super() | View已毁掉 |
| ServiceComponent | Service#onCreate() | Service#onDestroy() |
比较
ActivityComponent,ActivityRetainedComponent在运用装备更改(如反正屏)引起Activity重建后依然存在。
❓ Q:
ActivityRetainedComponent与ActivityComponent创立和毁掉机遇共同,为何ActivityRetainedComponent能够在装备更改后仍然存在,ActivityComponent则不可?
A:ActivityRetainedComponentManager会创立ActivityRetainedComponentViewModel,然后把ActivityRetainedComponent的实例存储在其间,ActivityRetainedComponentViewModel实例则经过ViewModelStore保存到Activity中。换句话说,其实就是借用了ViewModel的重建保存才能。
Component的默许绑定
Hilt会为生成的Component供给一些默许绑定,比方关于SingletonComponent,Hilt会为其默许绑定Application实例,关于ActivityComponent,Hilt则会为其默许绑定对应Activity的实例。除此之外,由于Hilt中Component的层次联系,Component也能够拜访到SubComponent供给的默许绑定。比方ActivityComponent也能够拜访到SingletonComponent中的Application实例。
下表给出了各种Component能够拜访到的默许绑定依靠项:
| Component | 默许绑定依靠项 |
|---|---|
| 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 |
效果域
Hilt中效果域的运用也与Dagger中相同。相同的Hilt也为生成的Component供给了预置的效果域注解,用于将依靠项实例的生命周期限制在对应Component的生命周期中:
| Component | 效果域 |
|---|---|
| SingletonComponent | @Singleton |
| ActivityRetainedComponent | @ActivityRetainedScoped |
| ViewModelComponent | @ViewModelScoped |
| ActivityComponent | @ActivityScoped |
| FragmentComponent | @FragmentScoped |
| ViewComponent | @ViewScoped |
| ViewWithFragmentComponent | @ViewScoped |
| ServiceComponent | @ServiceScoped |
在Hilt不支撑的类中完成注入
Dagger中,咱们能够在Component中编写返回依靠项实例的接口来对外露出依靠图中的依靠项。
@Component(modules = [CommonModule::class])
interface AppComponent {
fun inject(application: Application)
fun exposeSharedPreference(): SharedPreference
}
class MyClassCannotBeInject {
fun test(component: AppComponent) {
val sp = component.exposeSharedPreference()
...
}
}
但在Hilt中由于Component是主动生成的,咱们无法直接为其编写露出依靠项的接口。为此Hilt供给了@EntryPoint注解,@EntryPoint能够界说一个进口点,其它Hilt不支撑办理的类能够经过进口点拜访依靠图中的依靠项。@EntryPoint需求配合@InstallIn一同运用,标明要附加到哪个Component上。
@EntryPoint
@InstallIn(SingletonComponent::class)
interface ExampleEntryPoint {
fun sharedPreference(): SharedPreference
}
界说了进口点后,咱们就能够运用EntryPointAccessors中适当的静态办法获取拜访点。比方咱们的拜访点安装在SingletonComponent上,就需求运用fromApplication办法。
EntryPointAccessors.fromApplication(appContext,
ExampleEntryPoint::class.java)
val sp = hiltEntryPoint.sharedPreference()
完成原理
Hilt的拜访点在完成上实际上是在生成Component时,将@EntryPoint符号的接口作为其父接口继承其间露出的接口办法。
@Component(
modules = {
ApplicationContextModule.class,
CommonModule.class,
ActivityRetainedCBuilderModule.class,
ServiceCBuilderModule.class
}
)
@Singleton
public abstract static class SingletonC implements
HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
ServiceComponentManager.ServiceComponentBuilderEntryPoint,
SingletonComponent,
GeneratedComponent,
MyApplication_GeneratedInjector,
ExampleEntryPoint { }
public final class DaggerMyApplication_HiltComponents_SingletonC
extends MyApplication_HiltComponents.SingletonC {
...
@Override
public SharedPreference sharedPreference() {
return provideSharedPreferenceProvider.get();
}
}
资料
-
Google官方运用指引
运用 Hilt 完成依靠项注入 | Android 开发者 | Android Developers

