Dagger-android делятся зависимостями между Деятельностями - PullRequest
0 голосов
/ 16 мая 2018

Я использую dagger-android для DI.Есть несколько общих зависимостей, которые я хочу предоставить для каждой операции .Они зависят от класса Activity, но не передают определенную реализацию Activity.Например:

class NavigatorImpl(private val activity: Activity) : Navigator {..}

Теперь я должен написать один и тот же код для каждого ActivityModule:

@Module
class SomeActivityModule {

    @Provides
    fun navigator(activity: SomeActivity): Navigator = NavigatorImpl(activity)

    // some deps...

}

@Module
class AnotherActivityModule {

    @Provides
    fun navigator(activity: AnotherActivity): Navigator = NavigatorImpl(activity)

    // another deps...

}

Я пытался предоставить эти зависимости через AndroidSupportInjectionModule, но оказалось, что Dagger генерируетотдельные подмодули для каждого действия, и мы можем получить доступ к зависимости действия только в определенных модулях (SomeActivityModule и AnotherActivityModule в этом примере):

@Module(includes = [AndroidSupportInjectionModule::class])
interface AppInjectionModule {

    @PerActivity
    @ContributesAndroidInjector(modules = [SomeActivityModule::class])
    fun someActivity(): SomeActivity

    @PerActivity
    @ContributesAndroidInjector(modules = [AnotherActivityModule::class])
    fun anotherActivity(): AnotherActivity

    // we don't have any Activity in the graph -> throws an error
    @PerActivity
    @Provides
    fun navigator(navigator: NavigatorImpl): Navigator

}

Так, как я могу предоставить такие зависимости, не дублируякод в каждом ActivityModule?

1 Ответ

0 голосов
/ 17 мая 2018

Прежде всего вы кладете все свои общие вещи в модуль, который вы можете использовать повторно. (Также используйте инжектор конструктора с @Binds, как показано ниже

class Navigator @Inject constructor(activity : Activity) { /* ... */ }

@Module
interface BaseActivityModule {

    @Binds
    fun navigator(navigator: NavigatorImpl): Navigator

    // other bindings...

}

Затем вам нужно переключиться на пользовательские объявления подкомпонентов вместо @ContributesAndroidInjector. Есть открытый вопрос, связанный с , но сейчас вы должны написать шаблон.

Вы объявляете AndroidInjector.Factory, который связывает все, что вам нужно, затем вы используете его для компоновщика подкомпонентов вместо значения по умолчанию AndroidInjector.Builder.

object MyCustomInjector {

  abstract class ActivityBuilder<T : Activity> : AndroidInjector.Factory<T> {
    override fun create(instance: T): AndroidInjector<T> {
      seedInstance(instance)
      activity(instance)
      return build()
    }

    @BindsInstance
    abstract fun seedInstance(instance: T)

    @BindsInstance
    abstract fun activity(instance: Activity)

    abstract fun build(): AndroidInjector<T>
  }
}

@Module(subcomponents = [(SomeActivityModule.SomeActivitySubcomponent::class)])
abstract class SomeActivityModule {

  @Binds
  @IntoMap
  @ActivityKey(SomeActivity::class)
  internal abstract fun contributeSomeActivity(builder: SomeActivitySubcomponent.Builder): AndroidInjector.Factory<out Activity>

  @PerActivity
  @Subcomponent(modules = [BaseActivityModule::class])
  interface SomeActivityActivitySubcomponent : AndroidInjector<SomeActivity> {
    @Subcomponent.Builder
    abstract class Builder : MyCustomInjector.ActivityBuilder<SomeActivity>()
  }
}

Таким образом, ваш построитель подкомпонента связывает SomeActivity и Activity, а ваш подкомпонент включает BaseActivityModule с привязками, определенными выше.

Для получения дополнительной информации вы также можете взглянуть на этот связанный вопрос с несколькими дополнительными шагами ...

...