使用 Hilt 进行依赖注入

Hilt 是一个用于 Android 的依赖注入库,它减少了在项目中进行手动依赖注入的样板代码。进行手动依赖注入需要您手动构建每个类及其依赖项,并使用容器来重用和管理依赖项。

Hilt 通过为项目中的每个 Android 类提供容器并自动管理其生命周期,提供了一种在应用程序中使用 DI 的标准方法。Hilt 基于流行的 DI 库Dagger构建,以受益于 Dagger 提供的编译时正确性、运行时性能、可扩展性和Android Studio 支持。有关更多信息,请参阅Hilt 和 Dagger

本指南解释了 Hilt 及其生成的容器的基本概念。它还演示了如何引导现有应用使用 Hilt。

添加依赖项

首先,将hilt-android-gradle-plugin 插件添加到项目的根build.gradle 文件中

Groovy

plugins {
  ...
  id 'com.google.dagger.hilt.android' version '2.51.1' apply false
}

Kotlin

plugins {
  ...
  id("com.google.dagger.hilt.android") version "2.51.1" apply false
}

然后,应用 Gradle 插件并在您的app/build.gradle 文件中添加这些依赖项

Groovy

...
plugins {
  id 'kotlin-kapt'
  id 'com.google.dagger.hilt.android'
}

android {
  ...
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.51.1"
  kapt "com.google.dagger:hilt-compiler:2.51.1"
}

// Allow references to generated code
kapt {
  correctErrorTypes true
}

Kotlin

plugins {
  id("kotlin-kapt")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

dependencies {
  implementation("com.google.dagger:hilt-android:2.51.1")
  kapt("com.google.dagger:hilt-android-compiler:2.51.1")
}

// Allow references to generated code
kapt {
  correctErrorTypes = true
}

Hilt 使用Java 8 功能。要在您的项目中启用 Java 8,请将以下内容添加到app/build.gradle 文件中

Groovy

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

Kotlin

android {
  ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

Hilt 应用类

所有使用 Hilt 的应用都必须包含一个用@HiltAndroidApp 注释的Application 类。

@HiltAndroidApp 触发 Hilt 的代码生成,包括应用的基类,该基类用作应用程序级依赖项容器。

Kotlin

@HiltAndroidApp
class ExampleApplication : Application() { ... }

Java

@HiltAndroidApp
public class ExampleApplication extends Application { ... }

生成的 Hilt 组件附加到Application 对象的生命周期并向其提供依赖项。此外,它是应用的父组件,这意味着其他组件可以访问其提供的依赖项。

将依赖项注入到 Android 类中

一旦在Application 类中设置了 Hilt 并且应用程序级组件可用,Hilt 就可以向具有@AndroidEntryPoint 注释的其他 Android 类提供依赖项

Kotlin

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { ... }

Java

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity { ... }

Hilt 当前支持以下 Android 类

  • Application(通过使用@HiltAndroidApp
  • ViewModel(通过使用@HiltViewModel
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

如果使用@AndroidEntryPoint 注释 Android 类,则还必须注释依赖于它的 Android 类。例如,如果注释片段,则还必须注释使用该片段的任何活动。

@AndroidEntryPoint 为项目中的每个 Android 类生成一个单独的 Hilt 组件。这些组件可以从其各自的父类接收依赖项,如组件层次结构中所述。

要从组件获取依赖项,请使用@Inject 注释执行字段注入

Kotlin

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {

  @Inject lateinit var analytics: AnalyticsAdapter
  ...
}

Java

@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @Inject
  AnalyticsAdapter analytics;
  ...
}

Hilt 注入的类可以有其他也使用注入的基类。如果这些基类是抽象的,则不需要 @AndroidEntryPoint 注解。

要了解 Android 类在哪个生命周期回调中被注入,请参阅 组件生命周期

定义 Hilt 绑定

为了执行字段注入,Hilt 需要知道如何从相应的组件提供必要的依赖项实例。一个绑定包含将类型实例作为依赖项提供所需的信息。

向 Hilt 提供绑定信息的一种方法是构造函数注入。在类的构造函数上使用 @Inject 注解,告诉 Hilt 如何提供该类的实例。

Kotlin

class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

Java

public class AnalyticsAdapter {

  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(AnalyticsService service) {
    this.service = service;
  }
  ...
}

类的带注解构造函数的参数是该类的依赖项。在这个例子中,AnalyticsAdapter 的依赖项是 AnalyticsService。因此,Hilt 也必须知道如何提供 AnalyticsService 的实例。

Hilt 模块

有时无法进行构造函数注入。这可能由于多种原因造成。例如,您无法对接口进行构造函数注入。您也无法对您不拥有的类型(例如来自外部库的类)进行构造函数注入。在这些情况下,您可以使用Hilt 模块向 Hilt 提供绑定信息。

Hilt 模块是用 @Module 注解的类。与 Dagger 模块 一样,它告诉 Hilt 如何提供某些类型的实例。与 Dagger 模块不同的是,您必须使用 @InstallIn 注解 Hilt 模块,以告诉 Hilt 将在哪个 Android 类中使用或安装每个模块。

在 Hilt 模块中提供的依赖项可在与安装 Hilt 模块的 Android 类关联的所有生成的组件中使用。

使用 @Binds 注入接口实例

考虑 AnalyticsService 示例。如果 AnalyticsService 是一个接口,则您无法对其进行构造函数注入。相反,通过在 Hilt 模块内创建一个用 @Binds 注解的抽象函数来向 Hilt 提供绑定信息。

@Binds 注解告诉 Hilt 在需要提供接口实例时使用哪个实现。

带注解的函数向 Hilt 提供以下信息:

  • 函数返回类型告诉 Hilt 函数提供哪些接口的实例。
  • 函数参数告诉 Hilt 提供哪个实现。

Kotlin

interface AnalyticsService {
  fun analyticsMethods()
}

// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl @Inject constructor(
  ...
) : AnalyticsService { ... }

@Module
@InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {

  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

Java

public interface AnalyticsService {
  void analyticsMethods();
}

// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
public class AnalyticsServiceImpl implements AnalyticsService {
  ...
  @Inject
  AnalyticsServiceImpl(...) {
    ...
  }
}

@Module
@InstallIn(ActivityComponent.class)
public abstract class AnalyticsModule {

  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    AnalyticsServiceImpl analyticsServiceImpl
  );
}

Hilt 模块 AnalyticsModule 使用 @InstallIn(ActivityComponent.class) 进行注解,因为您希望 Hilt 将该依赖项注入到 ExampleActivity 中。此注解表示 AnalyticsModule 中的所有依赖项在应用程序的所有活动中都可用。

使用 @Provides 注入实例

接口并不是您无法进行构造函数注入类型的唯一情况。如果您不拥有该类(因为它来自外部库,例如 RetrofitOkHttpClientRoom 数据库),或者必须使用 构建器模式 创建实例,则也无法进行构造函数注入。

考虑前面的示例。如果您不直接拥有 AnalyticsService 类,则可以通过在 Hilt 模块内创建函数并使用 @Provides 注解该函数来告诉 Hilt 如何提供此类型的实例。

带注解的函数向 Hilt 提供以下信息:

  • 函数返回类型告诉 Hilt 函数提供哪些类型的实例。
  • 函数参数告诉 Hilt 相应类型的依赖项。
  • 函数体告诉 Hilt 如何提供相应类型的实例。Hilt 每次需要提供该类型的实例时都会执行函数体。

Kotlin

@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    // Potential dependencies of this type
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

Java

@Module
@InstallIn(ActivityComponent.class)
public class AnalyticsModule {

  @Provides
  public static AnalyticsService provideAnalyticsService(
    // Potential dependencies of this type
  ) {
      return new Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService.class);
  }
}

为同一类型提供多个绑定

在需要 Hilt 将同一类型的不同实现作为依赖项提供的情况下,必须向 Hilt 提供多个绑定。您可以使用限定符为同一类型定义多个绑定。

限定符是用于在类型具有多个已定义绑定时标识该类型的特定绑定的注解。

考虑此示例。如果您需要拦截对 AnalyticsService 的调用,可以使用带有 拦截器OkHttpClient 对象。对于其他服务,您可能需要以不同的方式拦截调用。在这种情况下,您需要告诉 Hilt 如何提供 OkHttpClient 的两个不同实现。

首先,定义将用于注解 @Binds@Provides 方法的限定符。

Kotlin

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class OtherInterceptorOkHttpClient

Java

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface AuthInterceptorOkHttpClient {}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
private @interface OtherInterceptorOkHttpClient {}

然后,Hilt 需要知道如何提供与每个限定符对应的类型的实例。在这种情况下,您可以使用带有 @Provides 的 Hilt 模块。这两种方法的返回类型相同,但限定符将它们标记为两个不同的绑定。

Kotlin

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  fun provideAuthInterceptorOkHttpClient(
    authInterceptor: AuthInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(authInterceptor)
               .build()
  }

  @OtherInterceptorOkHttpClient
  @Provides
  fun provideOtherInterceptorOkHttpClient(
    otherInterceptor: OtherInterceptor
  ): OkHttpClient {
      return OkHttpClient.Builder()
               .addInterceptor(otherInterceptor)
               .build()
  }
}

Java

@Module
@InstallIn(ActivityComponent.class)
public class NetworkModule {

  @AuthInterceptorOkHttpClient
  @Provides
  public static OkHttpClient provideAuthInterceptorOkHttpClient(
    AuthInterceptor authInterceptor
  ) {
      return new OkHttpClient.Builder()
                   .addInterceptor(authInterceptor)
                   .build();
  }

  @OtherInterceptorOkHttpClient
  @Provides
  public static OkHttpClient provideOtherInterceptorOkHttpClient(
    OtherInterceptor otherInterceptor
  ) {
      return new OkHttpClient.Builder()
                   .addInterceptor(otherInterceptor)
                   .build();
  }
}

您可以通过使用相应的限定符注解字段或参数来注入所需的特定类型。

Kotlin

// As a dependency of another class.
@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .client(okHttpClient)
               .build()
               .create(AnalyticsService::class.java)
  }
}

// As a dependency of a constructor-injected class.
class ExampleServiceImpl @Inject constructor(
  @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient
) : ...

// At field injection.
@AndroidEntryPoint
class ExampleActivity: AppCompatActivity() {

  @AuthInterceptorOkHttpClient
  @Inject lateinit var okHttpClient: OkHttpClient
}

Java

// As a dependency of another class.
@Module
@InstallIn(ActivityComponent.class)
public class AnalyticsModule {

  @Provides
  public static AnalyticsService provideAnalyticsService(
    @AuthInterceptorOkHttpClient OkHttpClient okHttpClient
  ) {
      return new Retrofit.Builder()
                  .baseUrl("https://example.com")
                  .client(okHttpClient)
                  .build()
                  .create(AnalyticsService.class);
  }
}

// As a dependency of a constructor-injected class.
public class ExampleServiceImpl ... {

  private final OkHttpClient okHttpClient;

  @Inject
  ExampleServiceImpl(@AuthInterceptorOkHttpClient OkHttpClient okHttpClient) {
    this.okHttpClient = okHttpClient;
  }
}

// At field injection.
@AndroidEntryPoint
public class ExampleActivity extends AppCompatActivity {

  @AuthInterceptorOkHttpClient
  @Inject
  OkHttpClient okHttpClient;
  ...
}

最佳实践是,如果将限定符添加到类型,请将限定符添加到提供该依赖项的所有可能方法。将基本实现或常用实现保留为没有限定符的做法容易出错,并可能导致 Hilt 注入错误的依赖项。

Hilt 中预定义的限定符

Hilt 提供了一些预定义的限定符。例如,由于您可能需要来自应用程序或活动的 Context 类,因此 Hilt 提供了 @ApplicationContext@ActivityContext 限定符。

假设示例中的 AnalyticsAdapter 类需要活动的上下文。以下代码演示了如何向 AnalyticsAdapter 提供活动上下文。

Kotlin

class AnalyticsAdapter @Inject constructor(
    @ActivityContext private val context: Context,
    private val service: AnalyticsService
) { ... }

Java

public class AnalyticsAdapter {

  private final Context context;
  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(
    @ActivityContext Context context,
    AnalyticsService service
  ) {
    this.context = context;
    this.service = service;
  }
}

有关 Hilt 中提供的其他预定义绑定,请参阅 组件默认绑定

Android 类的生成组件

对于可以在其中执行字段注入的每个 Android 类,都有一个关联的 Hilt 组件,您可以在 @InstallIn 注解中引用该组件。每个 Hilt 组件负责将其绑定注入到相应的 Android 类中。

前面的示例演示了在 Hilt 模块中使用 ActivityComponent

Hilt 提供以下组件:

Hilt 组件 注入器对象
SingletonComponent Application
ActivityRetainedComponent N/A
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent 使用 @WithFragmentBindings 注解的 View
ServiceComponent Service

组件生命周期

Hilt 会根据相应 Android 类的生命周期自动创建和销毁生成的组件类的实例。

生成的组件 创建于 销毁于
SingletonComponent Application#onCreate() Application 被销毁
ActivityRetainedComponent Activity#onCreate() Activity#onDestroy()
ViewModelComponent ViewModel 创建 ViewModel 被销毁
ActivityComponent Activity#onCreate() Activity#onDestroy()
FragmentComponent Fragment#onAttach() Fragment#onDestroy()
ViewComponent View#super() View 被销毁
ViewWithFragmentComponent View#super() View 被销毁
ServiceComponent Service#onCreate() Service#onDestroy()

组件作用域

默认情况下,Hilt 中的所有绑定都是无作用域的。这意味着每次您的应用请求绑定时,Hilt 都会创建一个所需类型的新实例。

在此示例中,每次 Hilt 将 AnalyticsAdapter 作为依赖项提供给其他类型或通过字段注入(如在 ExampleActivity 中)时,Hilt 都会提供一个新的 AnalyticsAdapter 实例。

但是,Hilt 也允许将绑定限定到特定组件。Hilt 只会为绑定限定到的组件的每个实例创建一次作用域绑定,并且对该绑定的所有请求都共享相同的实例。

下表列出了每个生成组件的作用域注解:

Android 类 生成的组件 作用域
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped
View ViewComponent @ViewScoped
使用 @WithFragmentBindings 注解的 View ViewWithFragmentComponent @ViewScoped
Service ServiceComponent @ServiceScoped

在此示例中,如果使用 @ActivityScopedAnalyticsAdapter 限定到 ActivityComponent,则 Hilt 会在相应活动的整个生命周期中提供相同的 AnalyticsAdapter 实例。

Kotlin

@ActivityScoped
class AnalyticsAdapter @Inject constructor(
  private val service: AnalyticsService
) { ... }

Java

@ActivityScoped
public class AnalyticsAdapter {

  private final AnalyticsService service;

  @Inject
  AnalyticsAdapter(AnalyticsService service) {
    this.service = service;
  }
  ...
}

假设 AnalyticsService 具有一个内部状态,该状态要求每次都使用相同的实例,不仅在 ExampleActivity 中,而且在应用程序的任何位置都需要使用相同的实例。在这种情况下,将 AnalyticsService 限定到 SingletonComponent 是合适的。结果是,每当组件需要提供 AnalyticsService 的实例时,它都会每次都提供相同的实例。

以下示例演示了如何在 Hilt 模块中将绑定限定到组件。绑定的作用域必须与安装它的组件的作用域匹配,因此在此示例中,必须将 AnalyticsService 安装在 SingletonComponent 中而不是 ActivityComponent 中。

Kotlin

// If AnalyticsService is an interface.
@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

  @Singleton
  @Binds
  abstract fun bindAnalyticsService(
    analyticsServiceImpl: AnalyticsServiceImpl
  ): AnalyticsService
}

// If you don't own AnalyticsService.
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {

  @Singleton
  @Provides
  fun provideAnalyticsService(): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

Java

// If AnalyticsService is an interface.
@Module
@InstallIn(SingletonComponent.class)
public abstract class AnalyticsModule {

  @Singleton
  @Binds
  public abstract AnalyticsService bindAnalyticsService(
    AnalyticsServiceImpl analyticsServiceImpl
  );
}

// If you don't own AnalyticsService.
@Module
@InstallIn(SingletonComponent.class)
public class AnalyticsModule {

  @Singleton
  @Provides
  public static AnalyticsService provideAnalyticsService() {
      return new Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService.class);
  }
}

要了解有关 Hilt 组件作用域的更多信息,请参阅Android 和 Hilt 中的作用域

组件层次结构

将模块安装到组件中允许将其绑定作为该组件或其组件层次结构中任何子组件中其他绑定的依赖项访问。

ViewWithFragmentComponent is under FragmentComponent. FragmentComponent
    and ViewComponent are under ActivityComponent. ActivityComponent is under
    ActivityRetainedComponent. ViewModelComponent is under
    ActivityRetainedComponent. ActivityRetainedComponent and ServiceComponent
    are under SingletonComponent.
图 1. Hilt 生成的组件层次结构。

组件默认绑定

每个 Hilt 组件都带有一组默认绑定,Hilt 可以将这些绑定作为依赖项注入到您自己的自定义绑定中。请注意,这些绑定对应于常规活动和片段类型,而不是任何特定子类。这是因为 Hilt 使用单个活动组件定义来注入所有活动。每个活动都有此组件的不同实例。

Android 组件 默认绑定
SingletonComponent Application
ActivityRetainedComponent Application
ViewModelComponent SavedStateHandle
ActivityComponent ApplicationActivity
FragmentComponent ApplicationActivityFragment
ViewComponent ApplicationActivityView
ViewWithFragmentComponent ApplicationActivityFragmentView
ServiceComponent ApplicationService

应用程序上下文绑定也可以使用@ApplicationContext访问。例如

Kotlin

class AnalyticsServiceImpl @Inject constructor(
  @ApplicationContext context: Context
) : AnalyticsService { ... }

// The Application binding is available without qualifiers.
class AnalyticsServiceImpl @Inject constructor(
  application: Application
) : AnalyticsService { ... }

Java

public class AnalyticsServiceImpl implements AnalyticsService {

  private final Context context;

  @Inject
  AnalyticsAdapter(@ApplicationContext Context context) {
    this.context = context;
  }
}

// The Application binding is available without qualifiers.
public class AnalyticsServiceImpl implements AnalyticsService {

  private final Application application;

  @Inject
  AnalyticsAdapter(Application application) {
    this.application = application;
  }
}

活动上下文绑定也可以使用@ActivityContext访问。例如

Kotlin

class AnalyticsAdapter @Inject constructor(
  @ActivityContext context: Context
) { ... }

// The Activity binding is available without qualifiers.
class AnalyticsAdapter @Inject constructor(
  activity: FragmentActivity
) { ... }

Java

public class AnalyticsAdapter {

  private final Context context;

  @Inject
  AnalyticsAdapter(@ActivityContext Context context) {
    this.context = context;
  }
}

// The Activity binding is available without qualifiers.
public class AnalyticsAdapter {

  private final FragmentActivity activity;

  @Inject
  AnalyticsAdapter(FragmentActivity activity) {
    this.activity = activity;
  }
}

在 Hilt 不支持的类中注入依赖项

Hilt 支持大多数常见的 Android 类。但是,您可能需要在 Hilt 不支持的类中执行字段注入。

在这些情况下,您可以使用@EntryPoint注解创建一个入口点。入口点是 Hilt 管理的代码和未管理的代码之间的边界。它是代码第一次进入 Hilt 管理的对象图的点。入口点允许 Hilt 使用 Hilt 不管理的代码来在依赖项图中提供依赖项。

例如,Hilt 不直接支持内容提供程序。如果您希望内容提供程序使用 Hilt 获取一些依赖项,则需要为每个所需的绑定类型定义一个用@EntryPoint注解的接口,并包含限定符。然后添加@InstallIn以指定要安装入口点的组件,如下所示

Kotlin

class ExampleContentProvider : ContentProvider() {

  @EntryPoint
  @InstallIn(SingletonComponent::class)
  interface ExampleContentProviderEntryPoint {
    fun analyticsService(): AnalyticsService
  }

  ...
}

Java

public class ExampleContentProvider extends ContentProvider {

  @EntryPoint
  @InstallIn(SingletonComponent.class)
  interface ExampleContentProviderEntryPoint {
    public AnalyticsService analyticsService();
  }
  ...
}

要访问入口点,请使用EntryPointAccessors中的适当静态方法。参数应该是组件实例或充当组件持有者的@AndroidEntryPoint对象。确保您作为参数传递的组件和EntryPointAccessors静态方法都与@EntryPoint接口上的@InstallIn注解中的 Android 类匹配。

Kotlin

class ExampleContentProvider: ContentProvider() {
    ...

  override fun query(...): Cursor {
    val appContext = context?.applicationContext ?: throw IllegalStateException()
    val hiltEntryPoint =
      EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint::class.java)

    val analyticsService = hiltEntryPoint.analyticsService()
    ...
  }
}

Java

public class ExampleContentProvider extends ContentProvider {

  @Override
  public Cursor query(...) {
    Context appContext = getContext().getApplicationContext();
    ExampleContentProviderEntryPoint hiltEntryPoint =
      EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class);
    AnalyticsService analyticsService = hiltEntryPoint.analyticsService();
  }
}

在此示例中,您必须使用ApplicationContext来检索入口点,因为入口点安装在SingletonComponent中。如果您要检索的绑定位于ActivityComponent中,则应改为使用ActivityContext

Hilt 和 Dagger

Hilt 基于Dagger依赖注入库构建,提供了一种将 Dagger 集成到 Android 应用程序中的标准方法。

关于 Dagger,Hilt 的目标如下:

  • 简化 Android 应用中与 Dagger 相关的基础设施。
  • 创建一组标准的组件和作用域,以简化设置、可读性和应用程序之间的代码共享。
  • 提供一种简单的方法来为各种构建类型(例如测试、调试或发布)提供不同的绑定。

由于 Android 操作系统实例化了许多它自己的框架类,因此在 Android 应用中使用 Dagger 需要编写大量样板代码。Hilt 减少了在 Android 应用程序中使用 Dagger 时涉及的样板代码。Hilt 自动生成并提供以下内容:

  • 用于集成 Android 框架类的 Dagger 组件,否则您需要手动创建这些组件。
  • 作用域注解,与 Hilt 自动生成的组件一起使用。
  • 预定义绑定,用于表示 Android 类,例如ApplicationActivity
  • 预定义限定符,用于表示@ApplicationContext@ActivityContext

Dagger 和 Hilt 代码可以共存于同一个代码库中。但是,在大多数情况下,最好使用 Hilt 来管理您在 Android 上对 Dagger 的所有使用。要迁移使用 Dagger 的项目到 Hilt,请参阅迁移指南将您的 Dagger 应用迁移到 Hilt 代码实验室

其他资源

要了解有关 Hilt 的更多信息,请参阅以下其他资源。

示例

代码实验室

博客