使用 Hilt 插入依附元件

Hilt 是 Android 的依附元件插入程式庫,可減少在專案中手動插入依附元件的樣板。手動插入依附元件時,您必須手動建構每個類別及其依附元件,並透過容器,重複使用及管理依附元件。

Hilt 提供在應用程式使用 DI 的標準做法,為專案的每個 Android 類別提供容器,並自動管理其生命週期。Hilt 以熱門的 DI 程式庫 Dagger 為基礎建構,且具備 Dagger 提供的編譯時間正確性、執行階段效能、擴充性和 Android Studio 支援等優勢。詳情請參閱「Hilt 和 Dagger」。

本指南說明 Hilt 的基本概念及其產生的容器。並包括示範如何啟動現有應用程式,以使用 Hilt。

新增依附元件

首先,請將 hilt-android-gradle-plugin 外掛程式新增至專案的根層級 build.gradle 檔案:

Groovy

buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
    }
}

Kotlin

buildscript {
    ...
    dependencies {
        ...
        classpath("com.google.dagger:hilt-android-gradle-plugin:2.38.1")
    }
}

接著,套用 Gradle 外掛程式,並在 app/build.gradle 檔案中新增以下依附元件:

Groovy

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

android {
    ...
}

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

Kotlin

plugins {
    kotlin("kapt")
    id("dagger.hilt.android.plugin")
}

android {
    ...
}

dependencies {
    implementation("com.google.dagger:hilt-android:2.38.1")
    kapt("com.google.dagger:hilt-android-compiler:2.38.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 並可供使用應用程式層級元件後,Hlt 就可為有 @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;
  }
  ...
}

註解類別建構函式的參數是該類別的依附元件。在這個範例中,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 中的所有依附元件都適用於應用程式的所有活動。

使用 @Provides 插入執行個體

介面不一定是建構函式插入類型的唯一案例。如果您不是類別的擁有者,插入建構函式功能將不能使用 (例如復古OkHttpClient,或聊天室資料庫),因為其來自外部資料庫,或者如果必須透過建構工具模式建立。

請參考上一個範例。如果您並未直接擁有 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 類別,您可以在 @InstallIn 註解中參照相關的 Hilt 元件。每個 Hilt 元件負責將其繫結插入至對應的 Android 類別。

以上範例示範如何在 Hilt 模組中使用 ActivityComponent

Hilt 提供下列元件:

Hilt 元件 注入器
SingletonComponent Application
ActivityRetainedComponent
ViewModelComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent View 含有 @WithFragmentBindings 註解
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
View 含有 @WithFragmentBindings 註解 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 模組中的元件。繫結範圍須需與已安裝元件的元件範圍相符,因此在本範例中,您必須在 SingletonComponent 中安裝 AnalyticsService,而非在 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 位於 FragmentComponent 之下。FragmentComponent 和 ViewComponent 位於 ActivityComponent 之下。ActivityComponent 位於 ActivityRetainedComponent 之下。ViewModelComponent 位於 ActivityRetainedComponent 之下。ActivityRetainedComponent 和 ServiceComponent 位於 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 無法直接支援內容供應器。如果您想讓內容供應器使用 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();
  }
}

在本範例中,由於進入點會安裝在 SingletonComponent 中,因此您必須使用 ApplicationContext 擷取進入點。如果您要擷取的繫結位於 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 程式碼研究室」。

其他資源

如要進一步瞭解 Hilt,請參閱下列其他資源:

範例

程式碼研究室

網誌