I decided to add clean architecture to my project, I added three separate modules to the project: domain, data, presentation (app) and I divided the code into thees three modules. After that, I had a problem with Dagger, when I try to build the application, it says that it cannot access the WeatherDataApiService (this is the interface in which I make an API request using the retrofit library) I transferred this interface to the data module. In general, the problem is that I do not understand how to properly organize dependency injection so that classes have access to each other. The problem is that when Dagger is being built, access to the data module is closed. The problem is that I need to correctly distribute the dependencies between the modules. At the moment, my dependencies between the modules are built in this way - presentation(app) depends on the domain module, and the domain module depends on the data module
This is the interface WeatherDataApiService
interface WeatherDataApiService {
@GET("/v2.0/forecast/daily")
fun getWeatherData(
@Query("city") city: String,
@Query("days") days: Int,
@Query("units") degreeType: String
):Single<WeatherDataApiModel>
companion object {
operator fun invoke(): WeatherDataApiService {
val key = "40a7956799be42f49bc8b6ac4bb8e432"
val requestInterceptor = Interceptor{chain->
val url = chain.request()
.url() // HttpUrl
.newBuilder() // HttpUrl.Builder
.addQueryParameter("key", key) // HttpUrl.Builder
.build()
val request = chain.request()
.newBuilder() // Request.Builder
.url(url) // Request.Builder
.build() // Request
return@Interceptor chain.proceed(request) // Response
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(requestInterceptor) // OkHttpClient.Builder()
.build()
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://api.weatherbit.io")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build()
.create(WeatherDataApiService::class.java)
}
}
}
This is the repository located in the domain module.
class WeatherDataRepositoryImpl @Inject constructor(
private val weatherDataApiService : WeatherDataApiService,
private val mapper : WeatherDataMapper
) : WeatherDataRepository {
override fun getWeatherData(
city: String,
days: Int,
degreeType: String
): Single<WeatherData> =
weatherDataApiService.getWeatherData(city, days, degreeType)
.map { mapper.mapWeather(it) }
}
This is the use case code where I use the repository
class FetchWeatherDataUseCase @Inject constructor(private val weatherDataRepository: WeatherDataRepository) {
fun fetchWeatherData(city: String,days: Int,degreeType: String): Single<WeatherData> {
return weatherDataRepository.getWeatherData(city,days,degreeType)
}
}
This is the code of the Dagger module which is in domain
@Module
class WeatherDataRepositoryModule {
@Provides
@Singleton
fun providerWeatherDataRepository(
mapper: WeatherDataMapper,
weatherDataApiService: WeatherDataApiService
): WeatherDataRepository =
WeatherDataRepositoryImpl(
weatherDataApiService,
mapper
)
@Provides
@Singleton
fun providerApiService() = WeatherDataApiService()
@Provides
fun providerMapper() = WeatherDataMapper()
}
This is the code of the Dagger module which is in presentation(app)
@Module
class WeatherDataModule {
@Provides
@Singleton
fun provideFetchWeatherDataUseCase(weatherDataRepository: WeatherDataRepository) =
FetchWeatherDataUseCase(weatherDataRepository)
}
This is the code of the Dagger Component which is in presentation(app)
@Singleton
@Component(modules = [WeatherDataModule::class, WeatherDataRepositoryModule::class])
interface WeatherDataComponent {
fun injectWeatherDataFragment(weatherDataFragment: WeatherDataFragment)
}
Here I am creating a dagger, the code is in presentation (app)
class App : Application() {
lateinit var weatherDataComponent: WeatherDataComponent
override fun onCreate() {
super.onCreate()
weatherDataComponent = DaggerWeatherDataComponent.create()
}
}
Error text - cannot access WeatherDataApiService