背景
根据兄弟姐妹子组件之间的docs依赖关系是不可能的,因此,剩下的另一种方法是组件依赖关系。我试图封装“资源库”类,以便UI只能访问“资源库”的实例,而不能访问“资源库”的实现细节。我的意思是 ApiModule 中的任何内容都不应公开。
ApiModule
@Module
class ApiModule {
@Provides
fun provideConnection(): Connection = //....
}
RepositoryModule
@Module (
includes = [
ApiModule::class
]
)
abstract class RepositoryModule {
@Provides
fun providesRepository(connection Connection): Repository = //.....
}
AppComponent
@Component (modules = [
AppModule::class,
RepositoryModule::class
])
interface AppComponent{
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
问题
现在,如果我创建一个 AppComponent 的子组件(比如说 ActivitySubComponent ),则所有绑定都在 RepositoryModule 和 ApiModule 模块将公开给该子组件。不过,我只想提供“存储库”,即可从 ActivitySubComponent
访问建议的解决方案
创建 RepositoryComponenet 和 ActivityComponent 组件使 AppComponenet 成为其依赖项:
AppComponent
@Component (modules = [
AppModule::class
])
interface AppComponent{
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
ActivityComponent
@Component(dependencies = [AppComponent::class], modules = [ActivityModule::class])
interface ActivityComponent {
fun inject(mainActivity: MainActivity)
@Component.Builder
interface Builder{
fun appComponent(appComponent: AppComponent): Builder
fun build(): ActivityComponent
}
}
RepositoryComponent
@Component(dependencies = [AppComponent::class], modules = [RepositoryModule::class])
interface RepositoryComponent {
}
问题是如何将“资源库”实例公开给同级 ActivityComponent 的绑定,或者将@Inject
公开给MainActivity?任何解释,更改我的配置的建议或可能解决我问题的文章的链接都将受到赞赏。
答案 0 :(得分:0)
如果我正确理解了您的问题,则您不想将AppComponent的所有依赖项公开给它的子组件。正如component documentation所说的(“组件依赖关系”部分)
请注意,只有通过供应方式公开的绑定才可以通过组件依赖项获得。
您应该为此目的使用组件依赖项。
下面是工作示例
class Connection
interface Repository
@Module
object AppModule {
@Provides
@Singleton
fun provideConnection() = Connection()
}
@Module(includes = [AppModule::class])
object RepositoryModule {
@Provides
@Singleton
fun provideRepository(connection: Connection) = object : Repository {}
}
@Singleton
@Component(modules = [AppModule::class, RepositoryModule::class])
interface AppComponent {
val repository: Repository
}
@Scope
@MustBeDocumented
@kotlin.annotation.Retention
annotation class ActivityScope
@ActivityScope
@Component(dependencies = [AppComponent::class])
interface ActivityComponent {
fun inject(activity: FakeActivity)
}
class FakeActivity {
@Inject
lateinit var repository: Repository
// uncomment this and code won't compile because connection isn't explicitly exposed in AppComponent
// @Inject
// lateinit var connection: Connection
}
fun main() {
val appComponent = DaggerAppComponent.create()
val activityComponent = DaggerActivityComponent.builder().appComponent(appComponent).build()
val fakeActivity = FakeActivity()
activityComponent.inject(fakeActivity)
println("hash: ${fakeActivity.repository}")
println("hash: ${appComponent.repository}")
}
我使用了作用域,因为我想每个应用程序只需要一个存储库实例。如果不清楚,请告诉我。