Recently I started to divide our application into smaller Android modules, but I'm having a hard time to make Dagger work the way I want it to.
My current dagger setup consist of:
- ApplicationComponent
marked with @Singleton
. This component is created on app start.
- UserSubComponent
marked with @UserScope
. This subcomponent is created when the user login.
Both these components is placed in my app
module together with my App
class who's responsible for creating both components.
In my login
module (Which is a parent to my app module, so it can't access anything in the app module) I have my AuthenticationManager
.
When the user login I use RxJava to signal from my AuthenticationManager
to App
, so the UserSubComponent
can be created.
My problem is that I need to access some dependencies from my UserSubComponent
, after it have been created, in my AuthenticationManager
so I can preload the user's data before moving on.
Module structure:
app (AppComponent & UserSubComponent)
^
|
login (AuthenticationManager) - feature 2 - feature 3
My App class:
class App : DaggerApplication() {
@Inject
lateinit var authenticationManager: AuthenticationManager
override fun onCreate() {
super.onCreate()
authenticationManager
.authenticationStateStream
.subscribe { state ->
if (state == AuthenticationState.AUTHENTICATED) {
AppInjector.userComponent.inject(this)
}
}
}
AuthenticationManager:
class AuthenticationManager @Inject constructor(loginApi: LoginApi) {
@Inject
lateinit var preLoader : PreLoader // This won't work because of different scope
val authenticationStateStream = Observable<AuthenticationState>()
fun login() {
if (success) {
authenticationStateStream.emit(AuthenticationState.AUTHENTICATED)
// UserSubComponent is now created
preLoader.preload()
}
}
}
App component
@Singleton
@Component(modules = [AppModule::class, AndroidSupportInjectionModule::class])
interface AppComponent : AndroidInjector<App> {
fun userComponentBuilder(): UserComponent.Builder
}
AppModule
@Module
class AppModule {
@Provides
@Singleton
fun provideLoginApi() = LoginApi()
}
UserSubComponent
@UserScope
@Subcomponent(modules = [UserModule::class, AndroidSupportInjectionModule::class])
interface UserComponent : AndroidInjector<App> {
@Subcomponent.Builder
interface Builder {
fun build(): UserComponent
}
}
UserModule
@Module
class UserModule {
@Provides
@UserScope
fun providesPreLoader() = PreLoader()
}
Can I somehow get this structure to work? Or what are my options when it comes to modules + dagger?
So after a lot of trying, I finally managed to solve my problem.
What I discovered was:
I found this article really helpful: https://proandroiddev.com/using-dagger-in-a-multi-module-project-1e6af8f06ffc