Search code examples
androidkotlindagger-2daggerdagger-hilt

Dagger error: repeats modules with scoped bindings or declarations:


I keep trying to solve this error. And i have no idea what to do. I have 3 subcomponents(astronomy, currentweather and weatherforecast), I also created scopes and modules for each. With an App and AppComponent class.

Astronomy sub:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.MainActivity
import dagger.Subcomponent

@AstronomyScope
@Subcomponent(modules = [AstronomyModule::class])
interface AstronomySubComponent {

    fun inject(weatherActivity: MainActivity)

    @Subcomponent.Factory
    interface Factory {
        fun create(): AstronomySubComponent
    }
}

CurrentWeather sub:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.MainActivity
import dagger.Subcomponent

@CurrentWeatherScope
@Subcomponent(modules = [CurrentWeatherModule::class])
interface CurrentWeatherSubComponent {

    fun inject(currentWeatherActivity: MainActivity)

    @Subcomponent.Factory
    interface Factory {
        fun create(): CurrentWeatherSubComponent
    }
}

WeatherForecast sub:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.MainActivity
import dagger.Subcomponent

@WeatherForecastScope
@Subcomponent(modules = [WeatherForecastModule::class])
interface WeatherForecastSubComponent {

    fun inject(weatherForecastActivity: MainActivity)

    @Subcomponent.Factory
    interface Factory {
        fun create(): WeatherForecastSubComponent
    }
}

App class:

package com.ghostdev.skycast

import android.app.Application
import com.ghostdev.skycast.presentation.di.AppComponent
import com.ghostdev.skycast.presentation.di.AstronomyModule
import com.ghostdev.skycast.presentation.di.AstronomySubComponent
import com.ghostdev.skycast.presentation.di.CurrentWeatherModule
import com.ghostdev.skycast.presentation.di.CurrentWeatherSubComponent
import com.ghostdev.skycast.presentation.di.DaggerAppComponent
import com.ghostdev.skycast.presentation.di.Injector
import com.ghostdev.skycast.presentation.di.WeatherDataModule
import com.ghostdev.skycast.presentation.di.WeatherForecastModule
import com.ghostdev.skycast.presentation.di.WeatherForecastSubComponent

class App: Application(), Injector {
    private lateinit var appComponent: AppComponent
    private val location = LocationProvider(applicationContext).getCurrentLocation()

    override fun onCreate() {
        super.onCreate()

        appComponent = DaggerAppComponent.builder()
            .currentWeatherModule(CurrentWeatherModule())
            .weatherForecastModule(WeatherForecastModule())
            .astronomyModule(AstronomyModule())
            .weatherDataModule(WeatherDataModule(BuildConfig.API_KEY, location))
            .build()

    }

    override fun createCurrentWeatherSubComponent(): CurrentWeatherSubComponent {
        return appComponent.currentWeatherComponent().create()
    }

    override fun createWeatherForecastSubComponent(): WeatherForecastSubComponent {
        return appComponent.weatherForecastComponent().create()
    }

    override fun createAstronomySubComponent(): AstronomySubComponent {
        return appComponent.astronomyComponent().create()
    }
}

App Component:

package com.ghostdev.skycast.presentation.di

import dagger.Component
import javax.inject.Singleton

@Singleton
@Component(modules = [AppModule::class, CurrentWeatherModule::class, WeatherForecastModule::class,  AstronomyModule::class, WeatherDataModule::class])
interface AppComponent {

    fun currentWeatherComponent(): CurrentWeatherSubComponent.Factory

    fun weatherForecastComponent(): WeatherForecastSubComponent.Factory

    fun astronomyComponent(): AstronomySubComponent.Factory

}

AstronomyModule:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.presentation.WeatherViewModelFactory
import com.ghostdev.skycast.repo.WeatherRepo
import dagger.Module
import dagger.Provides

@Module
class AstronomyModule {

    @AstronomyScope
    @Provides
    fun provideWeatherViewModelFactory(weatherRepo: WeatherRepo): WeatherViewModelFactory {
        return WeatherViewModelFactory((weatherRepo))
    }
}

CurrentWeatherModule:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.presentation.WeatherViewModelFactory
import com.ghostdev.skycast.repo.WeatherRepo
import dagger.Module
import dagger.Provides


@Module
class CurrentWeatherModule {

    @CurrentWeatherScope
    @Provides
    fun provideWeatherViewModelFactory(weatherRepo: WeatherRepo): WeatherViewModelFactory {
        return WeatherViewModelFactory((weatherRepo))
    }
}

WeatherForecastModule:

package com.ghostdev.skycast.presentation.di

import com.ghostdev.skycast.presentation.WeatherViewModelFactory
import com.ghostdev.skycast.repo.WeatherRepo
import dagger.Module
import dagger.Provides

@Module
class WeatherForecastModule {

    @WeatherForecastScope
    @Provides
    fun provideWeatherViewModelFactory(weatherRepo: WeatherRepo): WeatherViewModelFactory {
        return WeatherViewModelFactory((weatherRepo))
    }
}

Astronomy scope:

package com.ghostdev.skycast.presentation.di

import javax.inject.Scope

@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class AstronomyScope

CurrentWeatherScope:

package com.ghostdev.skycast.presentation.di

import javax.inject.Scope

@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class CurrentWeatherScope

WeatherForecastScope:

package com.ghostdev.skycast.presentation.di

import javax.inject.Scope

@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class WeatherForecastScope

Injector:

package com.ghostdev.skycast.presentation.di

interface Injector {

    fun createCurrentWeatherSubComponent(): CurrentWeatherSubComponent

    fun createWeatherForecastSubComponent(): WeatherForecastSubComponent

    fun createAstronomySubComponent(): AstronomySubComponent
}

Solution

  • Your AppComponent cannot (and should not) list the three modules AstronomyModule, CurrentWeatherModule, and WeatherForecastModule. Those are included in the individual subcomponents, and Dagger knows they are related subcomponents because you have them appropriately listed on your AppComponent. Once you remove those modules from AppComponent's definition, everything should work fine.