Кинжал 2: соответствующий ключ существует в подкомпоненте - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь использовать кинжал 2 для внедрения зависимостей в Kotlin. Граф зависимостей, который я пытаюсь создать, равен

Application-> Activity -> Fragment с каждым компонентом обеспечены необходимые привязки / провайдеры. Вот моя текущая структура:

AppModule.kt

@dagger.Module 
abstract class AppModule {

@Binds
abstract fun bindContext(application: Application): Context

@Binds
abstract fun bindApplication(application : Application) : Application
}

AppComponent.kt

@Singleton
@Component(modules = arrayOf(AppModule::class, 
AndroidInjectionModule::class, 
ActivityBuilder::class))
interface AppComponent : 
AndroidInjector<FreedomGuardianApp> {

@Component.Builder
abstract class Builder : AndroidInjector.Builder<FreedomGuardianApp>()
}

ActivityModule.kt

@Module
abstract class ActivityBuilder {

@PerActivity
@ContributesAndroidInjector(modules = arrayOf(MainActivityModule::class))
abstract fun bindMainActivity() : MainActivity
}

MainActivityModule.kt

@Module(includes = 
arrayOf(WatchFaceFragmentModule::class))
class MainActivityModule {

@Provides
fun adapter(activity: MainActivity): MyPagesAdapter {
    return MyPagesAdapter(activity.supportFragmentManager)
}
}

WatchFaceFragmentModule.kt

@Module
abstract class WatchFaceFragmentModule {

@PerFragment
@ContributesAndroidInjector
abstract fun contributeWatchFaceFragment(): WatchFaceFragment
}

WatchFaceProvidersModule.kt

@Module
class WatchFaceProvidersModule {
@Provides
fun gestureDetector(fragment: WatchFaceFragment): GestureDetectorCompat {
    return GestureDetectorCompat(fragment.context, fragment)
}

@Provides
@Named("textToSpeak")
fun textToSpeak(fragment: WatchFaceFragment): String {
    return fragment.resources.getString(R.string.time_string)
}

@Provides
fun textToSpeech(fragment: WatchFaceFragment): TextToSpeech {
    return TextToSpeech(fragment.context, fragment)
}
}

Я ввожу GestureDetectorCompat, String (textToSpeak), TextToSpeak в WatchFaceFragment.

Вот ошибка:

    public abstract interface AppComponent extends dagger.android.AndroidInjector<com.medicalguardian.freedomguardian.FreedomGuardianApp> {
                ^
  A binding with matching key exists in component: com.medicalguardian.freedomguardian.di.WatchFaceFragmentModule_ContributeWatchFaceFragment.WatchFaceFragmentSubcomponent
      com.medicalguardian.freedomguardian.ui.fragment.WatchFaceFragment is injected at
          com.medicalguardian.freedomguardian.ui.MainActivity.watchFaceFragment
      com.medicalguardian.freedomguardian.ui.MainActivity is injected at
          dagger.android.AndroidInjector.inject(T) [com.medicalguardian.freedomguardian.di.AppComponent ? com.medicalguardian.freedomguardian.di.ActivityBuilder_BindMainActivity.MainActivitySubcomponent]

Моя структура неверна? Я не делаю инъекцию в конструктор WatchFaceFragment, так как это не помогает. Я также использую поддержку кинжалов (DaggerFragment, DaggerApplication и т. Д.). Если я не внедряю фрагмент, а внедряю только MainActivity, все работает нормально. Как мне решить эту проблему? Заранее прошу прощения за длительное чтение. Любая помощь приветствуется.

1 Ответ

0 голосов
/ 09 января 2019

Вы не указали нам, куда вы включаете WatchFaceProvidersModule, но должен быть включен в вашу @ContributesAndroidInjector аннотацию в WatchFaceFragmentModule.kt, а не в AppComponent или ActivityModule:

@Module
abstract class WatchFaceFragmentModule {

  @PerFragment
  @ContributesAndroidInjector(modules = arrayOf(WatchFaceProvidersModule::class))
  abstract fun contributeWatchFaceFragment(): WatchFaceFragment
}

Это должно гарантировать, что при внедрении WatchFaceFragment (и GestureCompat и т. Д., Который ему требуется) у вас есть доступ к экземпляру WatchFaceFragment. В противном случае, как указано в комментариях David , инжектор для вашего FreedomGuardianApp или MainActivity не будет знать, какой WatchFaceFragment будет возвращен; возможно, еще не существует.

...