【问题标题】:Inject only certain params in constructor在构造函数中仅注入某些参数
【发布时间】:2018-06-06 06:43:40
【问题描述】:

我有主持人

class PhonePresenter @Inject constructor(
    private val preference: DataPreference,
    private val ioScheduler: Scheduler = Schedulers.io())

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

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

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

【问题讨论】:

    标签: android kotlin dagger-2 dagger


    【解决方案1】:

    用二级构造函数制作注入构造函数

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

    【讨论】:

    • 这在 Java 中也可以吗?
    • @octavian 在java中,只需创建另一个只接受DataPreference作为参数的构造函数。
    • @luffy, 在java中用ioSchedular调用第二个构造函数,也会初始化DataPreference参数吗?
    • @Arpit 不,DataPreference 只会通过 Dagger 注入初始自动
    • 适配器类中怎么做?
    【解决方案2】:

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

    想到了两种方法:

    1。使用 Dagger 注入

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

    @Qualifier
    @Retention(AnnotationRetention.RUNTIME)
    @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
    @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
    ) { ... }
    

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

    提供不同参数的正确方法是使用具有不同专用模块的不同组件,例如供测试用。或者在测试时手动调用构造函数。

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

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

    class PhonePresenter @Inject constructor(private val preference: DataPreference) { 
        private val ioScheduler = Schedulers.io()
    
        ... 
    }
    

    【讨论】:

    • 谢谢,我知道第一种方法,但我认为从模块中获取调度程序是开销。第二种方法不适合,因为我想在测试中替换 ioScheduler。
    • 好的,那么第一种方法适合您的需求。不用担心开销,只要 provideIoScheduler 没有作用域或不返回 LazyProvider Dagger 编译器 2.13+ 将能够内联调用 - 不会有运行时开销。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多