Dagger2: how to resolve a JobService?

Viewed 1098

I'm trying to update my simple android app to use Dagger2. I think I've managed to understand some of the basics and the basic stuff (activities, view models, helpers) are being created through it.

Now, there's still a small gotcha: the app has a button that, when pressed, must schedule a job service. I can refactor my jobservice so that its dependencies are passed through its constructor, but how do I instantiate it from my activity? In other words, how do I replace this code:

    val serviceComponent = ComponentName(getApplication(), DbUpdaterJob::class.java)
    var jobInfo = JobInfo.Builder(DB_UPDATER_JOB_ID, serviceComponent)
            .setRequiredNetworkType(networkType)
            .setPersisted(true)
            .build()

    val scheduler = getApplication<Application>().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
    val res = scheduler.schedule(jobInfo)

so that instantiation is relegated to dagger?

Thanks!

2 Answers

After some digging, it ended up being easier than I thought...So, I've created a new module for my job binding:

@Module
abstract class JobBindingModule {
    @ServiceScoped
    @ContributesAndroidInjector
    internal abstract fun provideDbUpdatedJob(): DbUpdaterJob
}

Btw, ServiceScoped is a new annotation which looks like this:

@Scope
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE, ElementType.METHOD)
annotation class ServiceScoped

I've added the module to my dagger component module collection. After that, I've replaced constructor parameter injection with property injection:

class DbUpdaterJob: JobService() {
    @Inject
    lateinit var dbManager: NewsManager

And, finally, I've overrided the onCreate method to inject the required dependencies:

override fun onCreate() {
    super.onCreate()
    AndroidInjection.inject(this)
}

And it seems to be working...

You need to define the providers:

@Provides
fun provideServiceComponent(app: Application): ComponentName =
        ComponentName(app, DbUpdaterJob::class.java) // assuming you have only one ServiceComponent


@Provides
fun provideJobInfo(
        serviceComponent: ComponentName
): JobInfo =
        JobInfo.Builder(DB_UPDATER_JOB_ID)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
                .setPersisted(true)
                .build()
@Provides
@Singleton
fun provideJobScheduler(app: Application): JobScheduler = app.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler

and then inject

@Inject constructor(
        jobInfo: JobInfo,
        scheduler: JobScheduler
) {
    val res = scheduler.schedule(jobInfo)
            ...
}

It gets more complicated if you want to be able to create different ComponentName or JobInfo etc. In that case you need to use @Named injections.

Related