Hilt dans des applications multimodules

La génération de code Hilt a besoin d'accéder à tous les modules Gradle qui utilisent Hilt. Le module Gradle qui compile votre classe Application doit comporter tous les modules Hilt et toutes les classes injectées par le constructeur dans ses dépendances transitives.

Si votre projet multimodules est composé de modules Gradle standards, vous pouvez utiliser Hilt comme décrit dans la section Injection de dépendances avec Hilt. Toutefois, ce n'est pas le cas avec les applications qui incluent des modules de fonctionnalités.

Hilt dans les modules de fonctionnalité

Dans les modules de fonctionnalité, la manière dont les modules dépendent généralement les uns des autres est inversée. Par conséquent, Hilt ne peut pas traiter les annotations dans les modules de fonctionnalité. Vous devez utiliser Dagger pour effectuer une injection de dépendances dans vos modules de fonctionnalité.

Vous devez utiliser des dépendances de composants pour résoudre ce problème avec les modules de fonctionnalité. Procédez comme suit :

  1. Déclarez une interface @EntryPoint dans le module app (ou dans tout autre module pouvant être traité par Hilt) avec les dépendances dont le module de fonctionnalité a besoin.
  2. Créez un composant Dagger qui dépend de l'interface @EntryPoint.
  3. Utilisez Dagger comme d'habitude dans le module de fonctionnalité.

Prenons l'exemple de la page Injection de dépendances avec Hilt. Supposons que vous ajoutiez un module de fonctionnalité login à votre projet. Vous mettez en œuvre la fonctionnalité de connexion avec une activité appelée LoginActivity. Cela signifie que vous ne pouvez obtenir des liaisons qu'à partir du composant d'application.

Pour cette fonctionnalité, vous avez besoin d'un OkHttpClient avec la liaison authInterceptor.

Commencez par créer une interface @EntryPoint installée dans SingletonComponent avec les liaisons dont le module login a besoin :

Kotlin

// LoginModuleDependencies.kt - File in the app module.

@EntryPoint
@InstallIn(SingletonComponent::class)
interface LoginModuleDependencies {

  @AuthInterceptorOkHttpClient
  fun okHttpClient(): OkHttpClient
}

Java

// LoginModuleDependencies.java - File in the app module.

@EntryPoint
@InstallIn(SingletonComponent.class)
public interface LoginModuleDependencies {

  @AuthInterceptorOkHttpClient
  OkHttpClient okHttpClient();
}

Pour effectuer une injection de champ dans LoginActivity, créez un composant Dagger qui dépend de l'interface @EntryPoint :

Kotlin

// LoginComponent.kt - File in the login module.

@Component(dependencies = [LoginModuleDependencies::class])
interface LoginComponent {

  fun inject(activity: LoginActivity)

  @Component.Builder
  interface Builder {
    fun context(@BindsInstance context: Context): Builder
    fun appDependencies(loginModuleDependencies: LoginModuleDependencies): Builder
    fun build(): LoginComponent
  }
}

Java

// LoginComponent.java - File in the login module.

@Component(dependencies = LoginModuleDependencies.class)
public interface LoginComponent {

  void inject(LoginActivity loginActivity);

  @Component.Builder
  interface Builder {
    Builder context(@BindsInstance Context context);
    Builder appDependencies(LoginModuleDependencies loginModuleDependencies);
    LoginComponent build();
  }
}

Une fois ces étapes terminées, utilisez Dagger comme vous le feriez d'habitude dans votre module de fonctionnalité. Par exemple, vous pouvez utiliser les liaisons de SingletonComponent comme dépendance d'une classe :

Kotlin

// LoginAnalyticsAdapter.kt - File in the login module.

class LoginAnalyticsAdapter @Inject constructor(
  @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient
) { ... }

Java

// LoginAnalyticsAdapter.java - File in the login module.

public class LoginAnalyticsAdapter {

  private final OkHttpClient okHttpClient;

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

Pour effectuer une injection de champ, créez une instance du composant Dagger à l'aide d'applicationContext pour obtenir les dépendances SingletonComponent :

Kotlin

// LoginActivity.kt - File in the login module.

class LoginActivity : AppCompatActivity() {

  @Inject
  lateinit var loginAnalyticsAdapter: LoginAnalyticsAdapter

  override fun onCreate(savedInstanceState: Bundle?) {
    DaggerLoginComponent.builder()
        .context(this)
        .appDependencies(
          EntryPointAccessors.fromApplication(
            applicationContext,
            LoginModuleDependencies::class.java
          )
        )
        .build()
        .inject(this)

    super.onCreate(savedInstanceState)
    ...
  }
}

Java

// LoginActivity.java - File in the login module.

public class LoginActivity extends AppCompatActivity {

  @Inject
  LoginAnalyticsAdapter loginAnalyticsAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    DaggerLoginComponent.builder()
        .context(this)
        .appDependencies(
          EntryPointAccessors.fromApplication(
            getApplicationContext(),
            LoginModuleDependencies.class
          )
        )
        .build()
        .inject(this);

    super.onCreate(savedInstanceState);
    ...
  }
}

Pour plus de contexte sur les dépendances de module dans les modules de fonctionnalité, consultez la page Dépendances des composants avec des modules de fonctionnalité.

Pour en savoir plus sur Dagger sur Android, consultez la page Utiliser Dagger dans des applications Android.