只在构造函数中注入某些参数

mol*_*kin 9 android kotlin dagger dagger-2

我有主持人

class PhonePresenter @Inject constructor(
    private val preference: DataPreference,
    private val ioScheduler: Scheduler = Schedulers.io())
Run Code Online (Sandbox Code Playgroud)

ioScheduler是默认参数。我只想注射preference: DataPreference. 现在我有例外

[dagger.android.AndroidInjector.inject(T)] io.reactivex.Scheduler cannot be provided without an @Provides-annotated method.
Run Code Online (Sandbox Code Playgroud)

有什么方法可以定义我想在构造函数中注入的参数吗?

小智 11

使用辅助构造函数进行注入构造函数

class PhonePresenter(
    private val preference: DataPreference,
    private val ioScheduler: Scheduler) {        
    @Inject constructor(preference: DataPreference) : this(preference, Schedulers.io())
}
Run Code Online (Sandbox Code Playgroud)


Eug*_*nec 5

Dagger负责注入,让它发挥作用。不要使用默认参数(Dagger 不在乎),这将迫使您对依赖项做出有意识的决定。

我想到了两种方法:

1.使用Dagger注入

创建一个限定符,以便 Dagger 可以区分您可能想要注入的调度程序类型和提供默认 IO 调度程序的模块。

@Qualifier
@MustBeDocumented
annotation class ForIo

@Module
class SchedulerModule {

    @Provides
    @ForIo
    fun provideIoScheduler(): Scheduler = Schedulers.io()
}

class PhonePresenter @Inject constructor(
    private val preference: DataPreference,
    @ForIo private val ioScheduler: Scheduler,
) { ... }
Run Code Online (Sandbox Code Playgroud)

像往常一样添加SchedulerModule到您的组件中。

提供不同参数的正确方法是使用不同的组件和专门用于测试的不同模块。或者在测试时您将手动调用构造函数。

2. 在这种情况下避免使用 Dagger

或者,您可以从构造函数参数中删除 IO 调度程序。名称表明它永远不会是其他任何东西,Schedulers.io()因此使其参数化没有什么意义;改为将其作为实现细节。

class PhonePresenter @Inject constructor(
    private val preference: DataPreference,
) {

    @VisibleForTesting
    internal var ioScheduler: Scheduler = Schedulers.io()

    ... 
}
Run Code Online (Sandbox Code Playgroud)

上面的代码示例允许您在测试中重写ioScheduler。否则你可以制作财产private