Skup się na aplikacjach składających się z wielu modułów

Generowanie kodu Hilt wymaga dostępu do wszystkich modułów Gradle, które używają Hilt. Moduł Gradle, który kompiluje klasę Application, musi w zależnościach przejściowych zawierać wszystkie moduły Hilt i klasy wstrzykiwane przez konstruktor.

Jeśli Twój projekt składający się z wielu modułów składa się ze zwykłych modułów Gradle, możesz używać Hilt w sposób opisany w artykule Wstrzykiwanie zależności za pomocą Hilt. Dotyczy to jednak aplikacji zawierających moduły funkcji.

Wbudowane moduły funkcji

W modułach funkcji sposób, w jaki moduły zazwyczaj zależą od siebie, jest odwrócony. Dlatego Hilt nie może przetwarzać adnotacji w modułach funkcji. Do wstrzykiwania zależności w modułach funkcji musisz użyć narzędzia Dagger.

Aby rozwiązać ten problem za pomocą modułów funkcji, musisz użyć zależności komponentów. Wykonaj te czynności:

  1. Zadeklaruj interfejs @EntryPoint w module app (lub w innym module, który może być przetwarzany przez Hilt) z zależnościami, których wymaga moduł.
  2. Utwórz komponent Dagger, który zależy od interfejsu @EntryPoint.
  3. W module funkcji użyj Daggera w zwykły sposób.

Przeanalizujmy przykład ze strony Wstrzykiwanie zależności za pomocą Hilt. Załóżmy, że do projektu dodajesz moduł funkcji login. Funkcję logowania wdrażasz za pomocą działania o nazwie LoginActivity. Oznacza to, że możesz pobierać powiązania tylko z komponentu aplikacji.

Do tej funkcji potrzebujesz elementu OkHttpClient z powiązaniem authInterceptor.

Najpierw utwórz interfejs @EntryPoint zainstalowany w SingletonComponent z powiązaniami, których wymaga moduł login:

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

Aby wstrzykiwać pola w LoginActivity, utwórz komponent Dagger zależny od interfejsu @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();
  }
}

Po wykonaniu tych czynności użyj narzędzia Dagger w zwykły sposób w module funkcji. Możesz na przykład użyć powiązań z SingletonComponent jako zależności klasy:

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

Aby wykonać wstrzykiwanie pól, utwórz instancję komponentu Dagger, korzystając z metody applicationContext w celu pobrania zależności 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);
    ...
  }
}

Więcej informacji o zależnościach modułów funkcji znajdziesz w artykule Zależności komponentów z modułami funkcji.

Więcej informacji o Dagger na Androidzie znajdziesz w artykule Używanie Daggera w aplikacjach na Androida.