class MyWorker(
context: Context,
params: WorkerParameters,
private val api: MyApi,
private val dataStore: DataStore
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
val data = api.getData()
dataStore.save(data)
Result.success()
} catch (e: Exception) {
Timber.e(e)
Result.failure()
}
}
}
WorkerFactory を用意する。
class MyWorkerFactory(
private val api: MyApi,
private val dataStore: DataStore
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
return if (workerClassName == MyWorker::class.java.name) {
MyWorker(appContext, workerParameters, api, dataStore)
} else {
null
}
}
}
default initializer を削除するための記述を AndroidManifest に追加する。
<manifest ...>
<application
...>
...
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:ignore="ExportedContentProvider"
tools:node="remove" />
</application>
</manifest>
Application で Configuration.Provider を実装し、getWorkManagerConfiguration() で返す Configuration で MyWorkerFactory を指定する。直接 MyWorkerFactory を setWorkerFactory() に渡してもいいが、DelegatingWorkerFactory を使うと複数の Factory から構成させる Factory を作ることができる。
class MyApplication : Application(), Configuration.Provider {
...
override fun getWorkManagerConfiguration(): Configuration {
val api = appComponent.api()
val dataStore = appComponent.dataStore()
val delegatingWorkerFactory = DelegatingWorkerFactory().apply {
addFactory(MyWorkerFactory(api, dataStore))
}
return Configuration.Builder()
.setWorkerFactory(delegatingWorkerFactory)
.build()
}
}
Subcomponent を使えば WorkerFactory と Worker 両方 Dagger に生成させることもできるし、なんなら Hilt には HiltWorkerFactory が用意されている。
参考
- Android Developers: Custom WorkManager Configuration and Initialization
- WorkerFactory
- DelegatingWorkerFactory