Andreas1234
Andreas1234

Reputation: 698

How to inject Worker class?

So first of all I created my worker class called UpdaterWorker. After that I overrided getWorkManagerConfiguration inside my application class. And I created a WorkerFactory class.

Is that all I have to do, or did I miss something?

How can I create an one time request?

When I try to inject updater worker to main activity, I get this error: Dagger does not support injecting @AssistedInject type, .workmanager.UpdaterWorker. Did you mean to inject its assisted factory type instead?

**Updater worker**

@HiltWorker
class UpdaterWorker @AssistedInject constructor(
    private val api: ReservationApi,
    private val updaterUrl: String,
    private val prefManager: PrefManager,
    @Assisted private val context: Context,
    @Assisted workerParams: WorkerParameters
) : Worker(context, workerParams) {
...
}

** Worker Factory**
class WorkerFactory @Inject constructor(
    private val api: ReservationApi,
    @param:Named("update_url") private val updaterUrl: String,
    private val prefManager: PrefManager,
) : WorkerFactory() {

    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker? {
        return when (workerClassName) {
            WorkerEnums.UpdaterWorker.name -> {
                UpdaterWorker(api, updaterUrl, prefManager, appContext, workerParameters)
            }
            else ->
                throw Resources.NotFoundException("Worker not found")
        }
    }
}
** My application class**
    override fun getWorkManagerConfiguration(): Configuration {
        return Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
    }

**Main Activity**
    @Inject
    lateinit var updaterWorker: UpdaterWorker

Upvotes: 2

Views: 2072

Answers (1)

Andrew
Andrew

Reputation: 4712

A WorkerFactory is not needed and furthermore, you don't need to (and can't) inject the Worker into any other class. Here is the right approach:

Worker

@HiltWorker
class UpdaterWorker @AssistedInject constructor(
    private val api: ReservationApi,
    private val updaterUrl: String,
    private val prefManager: PrefManager,
    @Assisted private val context: Context,
    @Assisted workerParams: WorkerParameters
) : Worker(context, workerParams) {
...
}

Usage of Worker (e.g here in viewmodel)

class MyTestViewModelForWorker(@ApplicationContext private val context: Context) : ViewModel() {
     private val myTestWork = OneTimeWorkRequestBuilder<UpdateWorker>
        .build()

    fun startManager() {
        WorkManager.getInstance(context).enqueue(myTestWork)
    }

}

Then, it is important to override the default workerfactory with the hiltfactory in you app class

Overriding default WorkerFactory

@HiltAndroidApp
class App : Application(), Configuration.Provider {
    @Inject lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration(): Configuration =
        Configuration.Builder().setWorkerFactory(workerFactory).build()
}

And finally, you need to remove the default workmanagerinitalizator inside your manifest:

AppManifest

<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:authorities="${applicationId}.workmanager-init"
    tools:node="remove" />

Next time, please read the documentation of hilt, because everything I wrote here is perfectly explained there and second of all, the approach I am showing here will change with the release of androidx.work:work-runtime-ktx:2.6.0

Upvotes: 10

Related Questions