Access Dagger subcomponent dependencies from parent android module
When Dagger tries to create an object of AuthenticationManager
, it will also try to inject any @Inject
annotated fields as well. And that doesn't work as you correctly pointed out that PreLoader
is from a different scope which essentially means that it is from a different component, i.e., UserComponent
.
Important thing to note here is that UserComponent
is not yet created at the point AuthenticationManager
object is first created by Dagger. And since PreLoader
is provided byUserComponent
, there is no way Dagger could inject that field. However you can inject that field into AuthenticationManager
by yourself.
Something like this:
class AuthenticationManager @Inject constructor(loginApi: LoginApi) {
// Remove the @Inject annotation and provide a custom setter which will pre-load user data
private lateinit var preLoader : PreLoader
set(preLoader) {
field = preLoader
preLoader.preload()
}
val authenticationStateStream = Observable<AuthenticationState>()
fun login() {
if (success) {
authenticationStateStream.emit(AuthenticationState.AUTHENTICATED)
// UserSubComponent is now created
// You can't do this here:
// preLoader.preload()
}
}
}
Your App class:
class App : DaggerApplication() {
@Inject
lateinit var authenticationManager: AuthenticationManager
override fun onCreate() {
super.onCreate()
authenticationManager
.authenticationStateStream
.subscribe { state ->
if (state == AuthenticationState.AUTHENTICATED) {
// Here you can directly set the PreLoader object yourself
authenticationManager.preLoader =
AppInjector.userComponent.preLoader()
}
}
}
}
In order to access PreLoader
object, you also need to modify your UserComponent
like this:
@UserScope
@Subcomponent(modules = [UserModule::class, AndroidSupportInjectionModule::class])
interface UserComponent : AndroidInjector<App> {
fun preLoader() : PreLoader // <-- Need to add this
@Subcomponent.Builder
interface Builder {
fun build(): UserComponent
}
}
So after a lot of trying, I finally managed to solve my problem.
What I discovered was:
- Don't use SubComponents when your app is divided into multiple modules.
- Each module needs it's own component (feature component)
I found this article really helpful: https://proandroiddev.com/using-dagger-in-a-multi-module-project-1e6af8f06ffc