使用 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 类。例如,如果注解了一个 Fragment,则还必须注解使用该 Fragment 的所有 Activity。

@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;
  }
  ...
}

类的带注解构造函数的参数是该类的依赖项。在示例中,AnalyticsAdapterAnalyticsService 作为依赖项。因此,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 中的所有依赖项在应用程序的所有 Activity 中都可用。

使用 @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 提供了一些预定义的限定符。例如,由于您可能需要来自应用程序或 Activity 的 Context 类,因此 Hilt 提供了 @ApplicationContext@ActivityContext 限定符。

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

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 会在对应 Activity 的整个生命周期内提供 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 模块中将绑定限定到组件的作用域。绑定的作用域必须与安装它的组件的作用域相匹配,因此在本例中,您必须在 SingletonComponent 而不是 ActivityComponent 中安装 AnalyticsService

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 可以将这些绑定作为依赖项注入到您自己的自定义绑定中。请注意,这些绑定对应于一般的 Activity 和 Fragment 类型,而不是任何特定的子类。这是因为 Hilt 使用单个 Activity 组件定义来注入所有 Activity。每个 Activity 都有此组件的不同实例。

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;
  }
}

Activity 上下文绑定也可以使用 @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,请参阅以下其他资源。

示例

代码实验室

博客