使用 Dagger 自定义 WorkManager
WorkManager https://developer.android.google.cn/topic/libraries/architecture/workmanager/ Android Jetpack https://developer.android.google.cn/jetpack/
Android Jetpack WorkManager | Android 中文教学视频 WorkManager 在 Kotlin 中的实践 WorkManager: 周期性任务 自定义 WorkManager —— 基础概念
在本篇文章中,我们将会讨论使用 Dagger 自定义配置相关的内容,包括:
在我们的 WorkerFactory 中使用 Dagger 注入参数 按需初始化
⚠️ 本文扩展自上一篇自定义 WorkManager 的文章。强烈建议在阅读本文之前先去阅读上一篇文章!
为什么是 Dagger
官方指南 https://developer.android.google.cn/training/dependency-injection/dagger-basics Codelab 实战教程 https://codelabs.developers.google.com/codelabs/android-dagger/index.html
回顾
使用 Dagger 将参数注入到 WorkerFactory
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Singleton
class MyWorkerFactory @Inject constructor(
service: DesignerNewsService
) : DelegatingWorkerFactory() {
init {
addFactory(myWorkerFactory(service))
// 在这里添加您应用中可能会使用的其他工厂
}
}
提示: 如果想要 Dagger 能够注入这个值,我们必须把它放进 Dagger 的图中。这就是为什么我们给 Factory 添加了一个 @inject 注解。
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): AppComponent
}
fun inject(application: MyApplication)
}
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
class MyApplication : Application(), Configuration.Provider {
// 另一个 @inject 变量
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.factory().create(applicationContext)
appComponent.inject(this)
}
...
}
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
class MyApplication : Application(), Configuration.Provider {
@Inject lateinit var myWorkerFactory: MyWorkerFactory
...
override fun getWorkManagerConfiguration(): Configuration =
Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.INFO)
.setWorkerFactory(myWorkerFactory)
.build()
...
}
生产环境示例
iosched
https://play.google.com/store/apps/details?id=com.google.samples.apps.adssched
2019 Android 开发者峰会应用
https://github.com/google/iosched/tree/adssched
ADSsched 分支 https://github.com/google/iosched/commit/886ef3b7c483760478406dde76fe637fccfd13a9#diff-a312c1c757f6f2c994b2542bc2d71dee
ConferenceDataWorker.kt
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
/**
* 一个用来刷新资源库(当应用活跃时)以及缓存(当应用不活跃时)中的会议数据的任务。
*/
class ConferenceDataWorker(
ctx: Context,
params: WorkerParameters,
private val refreshEventDataUseCase: RefreshConferenceDataUseCase
) : CoroutineWorker(ctx, params) {
override suspend fun doWork(): Result {
Timber.i("ConferenceDataService triggering refresh conference data.")
return try {
refreshEventDataUseCase(Unit)
Timber.d("ConferenceDataService finished successfully.")
// Finishing 意味着这个任务不需要被重新安排执行。
Result.success()
} catch (e: Exception) {
Timber.e("ConferenceDataService failed. It will retry.")
// 意味着 Worker 应该被重试
if (runAttemptCount < MAX_NUMBER_OF_RETRY) {
Result.retry()
} else {
Result.failure()
}
}
}
}
源码: ConferenceDataWorker.kt
ConferenceDataWorker.kt
https://github.com/google/iosched/blob/adssched/shared/src/main/java/com/google/samples/apps/iosched/shared/data/work/ConferenceDataWorker.kt
源码: ConferenceDataWorker.kt https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/main/java/com/google/samples/apps/iosched/shared/data/work/ConferenceDataWorker.kt#L29
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
class ConferenceDataWorkerFactory(
private val refreshEventDataUseCase: RefreshConferenceDataUseCase
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
return when (workerClassName) {
ConferenceDataWorker::class.java.name ->
ConferenceDataWorker(appContext, workerParameters, refreshEventDataUseCase)
else ->
// 返回 null,这样基类就可以代理到默认的 WorkerFactory
null
}
}
}
源码: ConferenceDataWorkerFactory.kt
源码: ConferenceDataWorkerFactory.kt https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/main/java/com/google/samples/apps/iosched/shared/data/work/ConferenceDataWorkerFactory.kt#L25
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Singleton
class IoschedWorkerFactory @Inject constructor(
refreshConferenceDataUseCase: RefreshConferenceDataUseCase
) : DelegatingWorkerFactory() {
init {
addFactory(ConferenceDataWorkerFactory(refreshConferenceDataUseCase))
}
}
源码: IoschedWorkerFactory.kt
IoschedWorkerFactory.kt
https://github.com/google/iosched/blob/adssched/shared/src/main/java/com/google/samples/apps/iosched/shared/data/work/IoschedWorkerFactory.kt
源码: IoschedWorkerFactory.kt
https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/main/java/com/google/samples/apps/iosched/shared/data/work/IoschedWorkerFactory.kt#L24
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Inject lateinit var workerConfiguration: Configuration
// 使用 DelegatingWorkerFactory 为 WorkManager 设置自定义配置
override fun getWorkManagerConfiguration(): Configuration {
return workerConfiguration
}
源码: MainApplication.kt
源码: MainApplication.kt https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/mobile/src/main/java/com/google/samples/apps/iosched/MainApplication.kt#L38
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Singleton
@Provides
fun provideWorkManagerConfiguration(
ioschedWorkerFactory: IoschedWorkerFactory
): Configuration {
return Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.DEBUG)
.setWorkerFactory(ioschedWorkerFactory)
.build()
}
源码: debugRelease SharedModule.kt
源码: debugRelease SharedModule.kt
https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/debugRelease/java/com/google/samples/apps/iosched/shared/di/SharedModule.kt#L184
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
@Singleton
@Provides
fun provideWorkManagerConfiguration(
ioschedWorkerFactory: IoschedWorkerFactory
): Configuration {
return Configuration.Builder()
.setWorkerFactory(ioschedWorkerFactory)
.build()
}
源码: staging SharedModule.kt
SharedModule.kt https://github.com/google/iosched/blob/adssched/shared/src/staging/java/com/google/samples/apps/iosched/shared/di/SharedModule.kt 源码: SharedModule.kt https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/staging/java/com/google/samples/apps/iosched/shared/di/SharedModule.kt#L135
/* Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
private fun scheduleFetchEventData() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val conferenceDataWorker = OneTimeWorkRequestBuilder<ConferenceDataWorker>()
.setInitialDelay(MINIMUM_LATENCY, TimeUnit.SECONDS)
.setConstraints(constraints)
.build()
val operation = WorkManager.getInstance(this)
.enqueueUniqueWork(
uniqueConferenceDataWorker,
ExistingWorkPolicy.KEEP,
conferenceDataWorker)
.result
operation.addListener(
{ Timber.i("ConferenceDataWorker enqueued..") },
{ it.run() }
)
}
源码: IoschedFirebaseMessagingService.kt
IoschedFirebaseMessagingService.kt https://github.com/google/iosched/blob/adssched/shared/src/main/java/com/google/samples/apps/iosched/shared/fcm/IoschedFirebaseMessagingService.kt 源码: IoschedFirebaseMessagingService.kt https://github.com/google/iosched/blob/f237889eb568e501add09ca0728af9760ea7a193/shared/src/main/java/com/google/samples/apps/iosched/shared/fcm/IoschedFirebaseMessagingService.kt#L51
至此,我们结束了探索如何使用 Dagger 把参数注入到您的 Worker,同时也了解了如何将 WorkManager 集成到 iosched 这类的大型应用中。
总结
推荐阅读