Hilt в многомодульных приложениях,Hilt в многомодульных приложениях

Для генерации кода Hilt требуется доступ ко всем модулям Gradle, использующим Hilt. Модуль Gradle, который компилирует ваш класс Application , должен иметь в своих транзитивных зависимостях все модули Hilt и классы, внедренные конструктором.

Если ваш многомодульный проект состоит из обычных модулей Gradle, вы можете использовать Hilt, как описано в разделе «Внедрение зависимостей с помощью Hilt» . Однако это не относится к приложениям, которые включают функциональные модули .

Рукоять в функциональных модулях

В функциональных модулях способ, которым модули обычно зависят друг от друга, перевернут. Следовательно, Hilt не может обрабатывать аннотации в функциональных модулях. Вы должны использовать Dagger для внедрения зависимостей в ваши функциональные модули.

Чтобы решить эту проблему с помощью функциональных модулей, необходимо использовать зависимости компонентов. Выполните следующие действия:

  1. Объявите интерфейс @EntryPoint в модуле app (или в любом другом модуле, который может обрабатываться Hilt) с зависимостями, необходимыми функциональному модулю.
  2. Создайте компонент Dagger, который зависит от интерфейса @EntryPoint .
  3. Используйте Dagger, как обычно, в функциональном модуле.

Рассмотрим пример со страницы «Внедрение зависимостей с помощью Hilt» . Предположим, вы добавляете в свой проект модуль функции login . Вы реализуете функцию входа в систему с помощью действия под названием LoginActivity . Это означает, что вы можете получить привязки только из компонента приложения.

Для этой функции вам понадобится OkHttpClient с привязкой authInterceptor .

Сначала создайте интерфейс @EntryPoint , установленный в SingletonComponent с привязками, необходимыми модулю login :

Котлин

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

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

  @AuthInterceptorOkHttpClient
  fun okHttpClient(): OkHttpClient
}

Ява

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

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

  @AuthInterceptorOkHttpClient
  OkHttpClient okHttpClient();
}

Чтобы выполнить внедрение полей в LoginActivity , создайте компонент Dagger, который зависит от интерфейса @EntryPoint :

Котлин

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

Ява

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

После завершения этих шагов используйте Dagger, как обычно, в своем функциональном модуле. Например, вы можете использовать привязки из SingletonComponent как зависимость класса:

Котлин

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

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

Ява

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

public class LoginAnalyticsAdapter {

  private final OkHttpClient okHttpClient;

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

Чтобы выполнить внедрение полей, создайте экземпляр компонента Dagger, используя applicationContext , чтобы получить зависимости SingletonComponent :

Котлин

// 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)
    ...
  }
}

Ява

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

Дополнительную информацию о зависимостях модулей в функциональных модулях см. в разделе Зависимости компонентов от функциональных модулей .

Дополнительную информацию о Dagger на Android см. в разделе «Использование Dagger в приложениях Android» .