I'm creating a pet project with Hilt, and perhaps I'm having this issue because I'm installing everything in SingletonComponent::class
, and perhaps I should create components for each one.
The pet project has a NetworkModule
, UserPrefsModule
, and the problem appeared when I was trying to create an Authenticator
for OkHttp3
.
This is my network module
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Singleton
@Provides
fun providesHttpLoggingInterceptor() = HttpLoggingInterceptor()
.apply {
if (BuildConfig.DEBUG) level = HttpLoggingInterceptor.Level.BODY
}
@Singleton
@Provides
fun providesErrorInterceptor(): Interceptor {
return ErrorInterceptor()
}
@Singleton
@Provides
fun providesAccessTokenAuthenticator(
accessTokenRefreshDataSource: AccessTokenRefreshDataSource,
userPrefsDataSource: UserPrefsDataSource,
): Authenticator = AccessTokenAuthenticator(
accessTokenRefreshDataSource,
userPrefsDataSource,
)
@Singleton
@Provides
fun providesOkHttpClient(
httpLoggingInterceptor: HttpLoggingInterceptor,
errorInterceptor: ErrorInterceptor,
authenticator: Authenticator,
): OkHttpClient =
OkHttpClient
.Builder()
.authenticator(authenticator)
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(errorInterceptor)
.build()
}
Then my UserPrefsModule
is :
@Module
@InstallIn(SingletonComponent::class)
object UserPrefsModule {
@Singleton
@Provides
fun provideSharedPreference(@ApplicationContext context: Context): SharedPreferences {
return context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE)
}
@Singleton
@Provides
fun provideUserPrefsDataSource(sharedPreferences: SharedPreferences): UserPrefsDataSource {
return UserPrefsDataSourceImpl(sharedPreferences)
}
}
Then I have an AuthenticatorModule
@Module
@InstallIn(SingletonComponent::class)
object AuthenticationModule {
private const val BASE_URL = "http://10.0.2.2:8080/"
@Singleton
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create())
.baseUrl(BASE_URL)
.client(okHttpClient)
.build()
@Singleton
@Provides
fun provideApiService(retrofit: Retrofit): AuthenticationService =
retrofit.create(AuthenticationService::class.java)
@Singleton
@Provides
fun providesAccessTokenRefreshDataSource(
userPrefsDataSource: UserPrefsDataSource,
authenticationService: AuthenticationService,
): AccessTokenRefreshDataSource = AccessTokenRefreshDataSourceImpl(
authenticationService, userPrefsDataSource
)
}
The problem started to happen when I created the AccessTokenRefreshDataSourceImpl
that I need the AuthenticationService
and UserPrefsDataSource
, and I'm getting this error :
error: [Dagger/DependencyCycle] Found a dependency cycle: public abstract static class SingletonC implements App_GeneratedInjector,
For each feature like Login, SignIn, Verification, etc.. I was creating a new @Module
as this :
@Module
@InstallIn(SingletonComponent::class)
interface SignInModule {
@Binds
fun bindIsValidPasswordUseCase(
isValidPasswordUseCaseImpl: IsValidPasswordUseCaseImpl,
): IsValidPasswordUseCase
@Binds
fun bindIsValidEmailUseCase(
isValidEmailUseCase: IsValidEmailUseCaseImpl,
): IsValidEmailUseCase
//Here in that Datasource I'm using the AuthenticationService from AuthenticationModule and it works
@Binds
fun bindSignInDataSource(
signInDataSourceImpl: SignInDataSourceImpl
): SignInDataSource
}
Constructor of AccessTokenAutenticator
class AccessTokenAuthenticator @Inject constructor(
private val accessTokenRefreshDataSource: AccessTokenRefreshDataSource,
private val userPrefsDataSource: UserPrefsDataSource,
) : Authenticator {
Constructor of AccessTokenRefreshDatasource
class AccessTokenRefreshDataSourceImpl @Inject constructor(
private val authenticationService: AuthenticationService,
private val userPrefsDataSource: UserPrefsDataSource,
) : AccessTokenRefreshDataSource {
Note I have everything in a @Module
separated by features for a future be able to modularise the app.