从父android模块访问Dagger子组件依赖项
最近,我开始将我们的应用程序划分为更小的Android模块,但我很难让Dagger按我希望的方式工作 我当前的匕首设置包括:从父android模块访问Dagger子组件依赖项,android,module,dagger-2,dagger,Android,Module,Dagger 2,Dagger,最近,我开始将我们的应用程序划分为更小的Android模块,但我很难让Dagger按我希望的方式工作 我当前的匕首设置包括: -ApplicationComponent标记为@Singleton。此组件在应用程序启动时创建。 -UserSubComponent标记为@UserScope。此子组件是在用户登录时创建的 这两个组件与负责创建这两个组件的myapp类一起放置在myapp模块中 在我的登录模块(它是我的应用程序模块的父模块,因此无法访问应用程序模块中的任何内容)中,我有我的Authent
-
ApplicationComponent
标记为@Singleton
。此组件在应用程序启动时创建。-
UserSubComponent
标记为@UserScope
。此子组件是在用户登录时创建的
这两个组件与负责创建这两个组件的myapp
类一起放置在myapp
模块中
在我的登录
模块(它是我的应用程序模块的父模块,因此无法访问应用程序模块中的任何内容)中,我有我的AuthenticationManager
。
当用户登录时,我使用RxJava从我的AuthenticationManager
向App
发送信号,这样就可以创建UserSubComponent
我的问题是,我需要在UserSubComponent
创建后,在我的AuthenticationManager
中访问一些依赖项,以便在继续之前预加载用户的数据
模块结构:
app (AppComponent & UserSubComponent)
^
|
login (AuthenticationManager) - feature 2 - feature 3
我的应用程序类:
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)
}
}
}
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()
}
}
}
}
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()
}
}
}
用户子组件
@UserScope
@Subcomponent(modules = [UserModule::class, AndroidSupportInjectionModule::class])
interface UserComponent : AndroidInjector<App> {
@Subcomponent.Builder
interface Builder {
fun build(): UserComponent
}
}
我能设法让这个结构工作吗?或者,对于模块+dagger,我有什么选择?当dagger尝试创建
AuthenticationManager
的对象时,它还将尝试插入任何@inject
注释字段。正如您正确指出的那样,preload
来自不同的范围,这本质上意味着它来自不同的组件,即UserComponent
这里需要注意的重要一点是,UserComponent
尚未在Dagger首先创建的AuthenticationManager
对象处创建。由于预加载程序
是由用户组件
提供的,所以Dagger无法注入该字段。但是,您可以自己将该字段插入到AuthenticationManager
中
大概是这样的:
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()
}
}
}
@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
}
}
为了访问preload
对象,您还需要修改UserComponent
,如下所示:
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()
}
}
}
@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
}
}
@UserScope
@子组件(模块=[UserModule::class,AndroidSupportInjectModule::class])
接口用户组件:AndroidJector{
fun preload():preload/所以经过多次尝试,我终于解决了我的问题
我发现:
- 当应用程序分为多个模块时,不要使用子组件
- 每个模块都需要自己的组件(功能组件)
我发现这篇文章非常有用:
@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
}
}