使用 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.56.2' apply false
}

Kotlin

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

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

Groovy

...
plugins {
  id 'com.google.devtools.ksp'
  id 'com.google.dagger.hilt.android'
}

android {
  ...
}

dependencies {
  implementation "com.google.dagger:hilt-android:2.56.2"
  ksp "com.google.dagger:hilt-compiler:2.56.2"
}

Kotlin

plugins {
  id("com.google.devtools.ksp")
  id("com.google.dagger.hilt.android")
}

android {
  ...
}

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

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 类中

一旦 Hilt 在您的 Application 类中设置完毕并且应用级组件可用,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 的上下文。以下代码演示了如何将 Activity 上下文提供给 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 不适用
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 模块中将绑定限定到组件。绑定的作用域必须与安装它的组件的作用域匹配,因此在此示例中,您必须将 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 可以将它们作为依赖项注入到您自己的自定义绑定中。请注意,这些绑定对应于通用的 Activity 和 Fragment 类型,而不是任何特定的子类。这是因为 Hilt 使用单个 Activity 组件定义来注入所有 Activity。每个 Activity 都有该组件的不同实例。

Android 组件 默认绑定
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

应用程序上下文绑定也可以使用 @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 不直接支持内容提供器。如果您希望内容提供器使用 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 自动生成的组件。
  • 预定义绑定,用于表示 ApplicationActivity 等 Android 类。
  • 预定义限定符,用于表示 @ApplicationContext@ActivityContext

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

其他资源

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

示例

Codelabs

博客