Кинжал: в компоненте существует привязка с соответствующим ключом - PullRequest
0 голосов
/ 14 мая 2018

Я использую Dagger 2.16 и следил за этой статьей для моей реализации кинжала. С этой реализацией все работало нормально, пока у меня не было только одного Activity (HomeActivity). Как только я начал внедрять Dagger в SplashScreenActivity. Я начал получать эту ошибку. Вот код из моего проекта

AppComponent.kt

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    AppModule::class,
    ActivityBuilder::class,
    ServiceBuilder::class,
    BroadcastRecieverBuilder::class])
interface AppComponent : AndroidInjector<MyApp> {
    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}

AppModule.kt

@Module()
class AppModule {

    @Provides
    @Singleton
    fun provideContext(application: MyApp): Context {
        return application
    }

    @Provides
    @Singleton
    fun provideRestService(retrofit: Retrofit): RestService {
        return retrofit.create(RestService::class.java)
    }
    ...
}

ActivityBuilder.kt

@Module
abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = [HomeActivityModule::class])
    @PerActivity
    abstract fun bindHomeActivity(): HomeActivity

    @ContributesAndroidInjector(modules = [SplashScreenModule::class])
    @PerActivity
    abstract fun bindSplashActivity(): SplashScreenActivity
}

BaseActivity.kt

abstract class BaseActivity<V : BaseView, P : MvpBasePresenter<V>> :
        MvpActivity<V, P>(), BaseView, HasSupportFragmentInjector {
    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    @Inject
    lateinit var mPresenter: P

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun createPresenter(): P = mPresenter

    override fun supportFragmentInjector(): AndroidInjector<Fragment> {
        return fragmentInjector
    }
}

У меня есть собственная BaseActivity вместо DaggerActivity, потому что я должен наследовать от MvpActivity Мосби.

SplashScreenModule.kt

@Module
abstract class SplashScreenModule {

    @Binds
    @PerActivity
    internal abstract fun splashPresenter(splashPresenter: SplashScreenPresenter): BasePresenter<*>
}

HomeActivityModule.kt

@Module
abstract class HomeActivityModule {

    @Binds
    @PerActivity
    internal abstract fun homePresenter(homePresenter: HomeActivityPresenter): BasePresenter<*>

    @ContributesAndroidInjector(modules = [DownloadFragmentModule::class])
    @PerFragment
    internal abstract fun downloadsFragment(): DownloadsFragment
}

Теперь, когда я строю это, я получаю сообщение об ошибке следующим образом

error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.realtime.app.MyApp> {
                ^
  A binding with matching key exists in component: com.realtime.dagger.ActivityBuilder_BindHomeActivity.HomeActivitySubcomponent
      java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
          dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
      dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
          com.realtime.core.BaseActivity.fragmentInjector
      com.realtime.splashScreen.SplashScreenActivity is injected at
          dagger.android.AndroidInjector.inject(T)
  component path: com.realtime.dagger.AppComponent → com.realtime.dagger.ActivityBuilder_BindSplashActivity.SplashScreenActivitySubcomponent

Я прошел через другую подобную очередь, такую ​​как this , но не мог связать это с тем, с чем я столкнулся. Чего мне не хватает?

Обновление: На данный момент я не наследую BaseActivity в SplashScreenActivity, чтобы избежать инъекций fragmentInjector: DispatchingAndroidInjector<Fragment>. Пока он работает, так как у меня нет фрагмента в SplashScreenActivity.

1 Ответ

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

Работает для HomeActivity, потому что связывает фрагмент:

@ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment

SplashScreenActivity - нет.


AndroidInjection использует DispatchingAndroidInjector для обработки инъекций во время выполнения, чтов основном содержит Map классов для их компонентов.Эта карта должна быть введена как все остальное.В случае HomeActivity объявление фрагмента в модуле генерирует привязку для карты, которую затем можно внедрить.

Поскольку в всплывающей активности нет фрагмента, кинжал не знает ни о каких привязках, не говоря уже о каких-либо привязках.карта.Вот почему он жалуется, что он не может быть предоставлен .

Подробнее о 1019 * можно прочитать здесь .

Toчтобы этого не происходило, вы должны зарегистрировать AndroidInjectionModule в своем AppComponent, который просто содержит объявления для пустых карт.

Хотя он содержит объявление для android.app.Fragment, он не дляandroid.support.v4.app.Fragment, откуда и возникает ошибка.


Поэтому, чтобы исправить эту конкретную ошибку, вы должны добавить AndroidSupportInjectionModule к вашему компоненту, который также включает в себя привязки поддержки,предоставление пустой карты, когда в задании нет фрагментов.

@Component(modules = [AndroidSupportInjectionModule::class, /* ... */])
interface AppComponent { /* ... */ }
...