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?
While dependent components can have 1 or more parents SubComponent can only have one.
In Dagger 2, component is the main container-like object that binds all the dependencies (or it's factory). Subcomponent are components that is like an extension to its parent component. It can be used for. Partition the dependencies into different compartments.
There are two ways to communicate between Modules in Android: Using Callbacks/ Interfaces. Using Local Broadcast.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With