Overview
You need to look at WorkerFactory, available from 1.0.0-alpha09
onwards.
Previous workarounds relied on being able to create a Worker
using the default 0-arg constructor, but as of 1.0.0-alpha10
that is no longer an option.
Example
Let's say that you have a Worker
subclass called DataClearingWorker
, and that this class needs a Foo
from your Dagger graph.
class DataClearingWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
lateinit var foo: Foo
override fun doWork(): Result {
foo.doStuff()
return Result.SUCCESS
}
}
Now, you can't just instantiate one of those DataClearingWorker
instances directly. So you need to define a WorkerFactory
subclass that can create one of them for you; and not just create one, but also set your Foo
field too.
class DaggerWorkerFactory(private val foo: Foo) : WorkerFactory() {
override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): ListenableWorker? {
val workerKlass = Class.forName(workerClassName).asSubclass(Worker::class.java)
val constructor = workerKlass.getDeclaredConstructor(Context::class.java, WorkerParameters::class.java)
val instance = constructor.newInstance(appContext, workerParameters)
when (instance) {
is DataClearingWorker -> {
instance.foo = foo
}
// optionally, handle other workers
}
return instance
}
}
Finally, you need to create a DaggerWorkerFactory
which has access to the Foo
. You can do this in the normal Dagger way.
@Provides
@Singleton
fun workerFactory(foo: Foo): WorkerFactory {
return DaggerWorkerFactory(foo)
}
Disabling Default WorkManager Initialization
You'll also need to disable the default WorkManager
initialization (which happens automatically) and initialize it manually.
How you do this depends on the version of androidx.work
that you're using:
2.6.0 and onwards:
In AndroidManifest.xml
, add:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="YOUR_APP_PACKAGE.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
Pre 2.6.0:
In AndroidManifest.xml
, add:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="YOUR_APP_PACKAGE.workmanager-init"
android:enabled="false"
android:exported="false"
tools:replace="android:authorities" />
Be sure to replace YOUR_APP_PACKAGE with your actual app's package. The <provider
block above goes inside your <application
tag.. so it's a sibling of your Activities
, Services
etc...
In your Application
subclass, (or somewhere else if you prefer), you can manually initialize WorkManager
.
@Inject
lateinit var workerFactory: WorkerFactory
private fun configureWorkManager() {
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(this, config)
}