Dagger 2.10 : внедрение зависимости с контекстом активности в действиях и фрагментах

#android #dagger-2

#Android #dagger-2

Вопрос:

У меня есть класс с именем, AlertManager для Activity которого требуется, чтобы экземпляр отображал Toast и AlertDialog .

 class AlertManager @Inject constructor(private val activity: Activity) {

    fun showToast(message: String) {
        Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
    }
}
  

Теперь я хочу AlertManager использовать зависимость в двух действиях HomeActivity amp; ProductsActivity . В настоящее время я создал модули для каждого Activity подобного:

 @Module
class HomeActivityModule {
    @Provides
    @ActivityContext
    fun provideAlertManager(activity: HomeActivity) = AlertManager(activity)
}
  

И

 @Module
class ProductsActivityModule {
    @Provides
    @ActivityContext
    fun provideAlertManager(activity: ProductsActivity) = AlertManager(activity)
}
  

И привязать их к Dagger, как

 @Module
abstract class ActivityProvider {
    @ContributesAndroidInjector(modules = [HomeActivityModule::class])
    @ActivityContext
    abstract fun bindHomeActivity(): HomeActivity

    @ContributesAndroidInjector(modules = [ProductsActivityModule::class])
    @ActivityContext
    abstract fun bindProductsActivity(): ProductsActivity
}
  

Теперь мои вопросы:

1) Как я могу избежать создания модулей для каждого activities и иметь общие, ActivityModule которые я могу связать с чем Activity угодно?

2) Допустим, у меня есть фрагмент с именем HomeFragment inside HomeActivity , тогда как я могу внедрить тот же AlertManager экземпляр HomeActivity внутри фрагмента?

Я застрял здесь довольно долго и пытался многое найти в Интернете, но я не могу найти какой-либо блог или руководство, которые могут помочь мне достичь того, что я ищу. Если кто-то может указать мне правильное направление, я буду благодарен.

Комментарии:

1. На GitHub есть связанная с этим проблема

Ответ №1:

1) Как я могу избежать создания модулей для каждого activities и иметь общий ActivityModule, который я могу связать с любым Activity, который я хочу?

У вас может быть какой-то AlertManagerModule, в который вы добавляете общую активность.

 @Provides
fun provideAlertManager(activity: Activity) = AlertManager(activity)
  

Вам все равно придется создавать отдельные модули activity. Одно изменение, которое вы можете внести, это:

 @Module
abstract class HomeActivityModule {
    @Binds
    abstract fun providesActivity(activity: HomeActivity) : Activity
}
  

А затем вы можете добавить их в класс ActivityProvider:

 @Module
abstract class ActivityProvider {
    @ContributesAndroidInjector(modules = [HomeActivityModule::class, AlertManagerModule::class])
    abstract fun bindHomeActivity(): HomeActivity

    @ContributesAndroidInjector(modules = [ProductsActivityModule::class, AlertManagerModule::class])
    abstract fun bindProductsActivity(): ProductsActivity
}
  

2) Допустим, у меня есть фрагмент с именем HomeFragment внутри HomeActivity, тогда как я могу внедрить тот же экземпляр AlertManager HomeActivity внутри фрагмента?

Поскольку вы используете DaggerActivity и, скорее всего, используете DaggerFragment, фрагмент, созданный в HomeFragment, может напрямую получать AlertManager, просто используя аннотацию @Inject во фрагменте, который вы добавили в HomeActivityModule:

  @Module
 abstract class HomeActivityModule {

    @Binds
    abstract fun providesActivity(activity: HomeActivity) : Activity

    @FragmentScope
    @ContributesAndroidInjector
    abstract fun providesHomeFragment() : HomeFragment;
}
  

Комментарии:

1. Ваше первое решение сработало, и я могу привязать экземпляр таким образом. Все еще необходимо создавать отдельные модули, но предложенный вами способ намного лучше. Однако я не могу внедрить AlertManager во фрагмент. Я все еще получаю: android.app.Activity cannot be provided without an @Inject constructor or an @Provides-annotated method .

2. @SandipSoni Вместо того, чтобы устанавливать @ContributesAndroidInjector HomeFragment непосредственно в свой AppComponent, установите его в тот же массив модулей, что и [HomeActivityModule::class, AlertManagerModule::class] . Это означает, что ваш подкомпонент HomeFragment находится под подкомпонентом HomeActivity . Также убедитесь, что ваш HomeActivity расширяется DaggerActivity .

3. @SandipSoni Я вижу, в чем проблема. Вы должны добавить HomeFragment ContributesAndroidInjector не в отдельный appmodule, а внутри HomeActivityModule.

4. Спасибо, ребята, это наконец сработало. Я недоволен той частью, где мне все еще приходится создавать module для каждого activity, но, похоже, на данный момент это единственный способ и, следовательно, принятие этого ответа. Еще раз спасибо 🙂