Damian Moliński Damian Moliński - 2 months ago 37
Android Question

rx.Scheduler cannot be provided without an @Provides- or @Produces-annotated method

I do have two custom annotations

@Qualifier
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class IOScheduler


and

@Qualifier
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class UIScheduler


I'm using them in my module

@Module
class UiModule {

@Provides
@UIScheduler
fun provideUiScheduler(): Scheduler = AndroidSchedulers.mainThread()

@Provides
@IOScheduler
fun provideIOScheduler(): Scheduler = Schedulers.io()

}


Of course module is added to my component, and when i'm trying to inject them it says


rx.Scheduler cannot be provided without an @Provides- or
@Produces-annotated method.


injecting

class MainPresenter(val view: MainContract.View) : MainContract.Presenter {

@Inject lateinit var api: ApiServices
@Inject lateinit var databaseManager: DatabaseManager
@Inject @UIScheduler lateinit var observeScheduler: Scheduler
@Inject @IOScheduler lateinit var subscribeScheduler: Scheduler
...
}


Funny think is that i'm using almost same think with injecting Gson for my ApiClient and it works perfectly

@Module
class ApiModule {

...

@Provides
@Singleton
@DefaultGson
fun providesGson(): Gson = GsonBuilder().create()

@Provides
@Singleton
@FormatDateGson
fun providesGsonFormatTimestamp(): Gson = GsonBuilder().setDateFormat(Constants.TIME_STAMP_FORMAT).create()
}

@Singleton
class ApiClient @Inject constructor(@DefaultGson val gson: Gson, val sharedPreferences: SharedPrefsUtils) {
...
}


In additional i can say that i do have same modules / providers structure in my java projects and it works just fine.

Answer

Use custom annotations with field: target e.g.

@Inject @field:IOScheduler lateinit var subscribeScheduler: Scheduler

In other news: Dagger refuses to do the following:

@Inject internal  var something: Boolean  = false // or
@Inject protected var toolbar:   Toolbar? = null

The error looks like this:

Dagger does not support injection into private fields

This affects any variables without the lateinit modifier.

You'll have to expose primitives in your component and inject them manually.

Just specify the set: target so injection is done via public/internal/protected setter instead of the private backing field like this:

@set:Inject internal  var something: Boolean  = false // or
@set:Inject protected var toolbar:   Toolbar? = null
Comments