android - WorkManager 不使用自定义配置
问题描述
我正在尝试使用 运行同步作业,WorkManager
但是似乎传递的配置被部分忽略了。
下面是我的实现:
应用程序:
class App : Application(), HasAndroidInjector, Configuration.Provider {
@Inject
lateinit var workerConfiguration: Configuration
override fun getWorkManagerConfiguration(): Configuration {
Timber.tag(javaClass.name).d("RRR config ${workerConfiguration.executor.run { Thread.currentThread().name }}")
return workerConfiguration
}
}
模块注入:如您所见,我设置了 1 个 SingleThreaded Executor 与一些特定ThreadFactory
和自定义WorkerFactory
@Singleton
@Provides
fun provideWorkManagerConfiguration(
globalWorkerFactory: GlobalWorkerFactory
): Configuration {
val threadFactory = ThreadFactoryBuilder().setNameFormat("sync-worker-thread-%d").build()
val executor = Executors.newSingleThreadExecutor(threadFactory)
executor.submit { Log.d(javaClass.name,"RRR executor thread = ${Thread.currentThread().name}") }
return Configuration.Builder()
.setWorkerFactory(globalWorkerFactory)
.setExecutor(executor)
.build()
}
GlobalWorkingFactory:用于向workers注入一些参数
@Singleton
class GlobalWorkerFactory @Inject constructor(
api: API
) : DelegatingWorkerFactory() {
init {
Log.d(javaClass.name, "RRR adding factory ${Thread.currentThread().name}")
addFactory(WorkerFactory(api))
}
}
工人工厂:
CustomWorkerFactory(
private val api: API,
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): CoroutineWorker? {
return when (workerClassName) {
SyncWorker::class.java.name -> {
Log.d(javaClass.name, "RRR gettting sync worker on ${Thread.currentThread().name}")
SyncWorker(appContext, workerParameters, api)
}
else ->
null
}
}
}
Sync Worker 执行一些长时间运行的调用:
class SyncWorker constructor(
appContext: Context,
workerParams: WorkerParameters,
private val api: API):
CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
Timber.d("RRR START sync file ${uploadingFile.file.name} on thread ${Thread.currentThread().name}")
syncfile()
Timber.d("RRR returning result for ${uploadingFile.file.name}")
}
最后是我排队工作的方式:
fun addFileToWorker(context: Context, uploadingFile: UploadingFile) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
val syncWorkerRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setInputData(
workDataOf(
"uploadingFile" to uploadingFileAdapter.toJson(
uploadingFile
)
)
)
.addTag(SYNC_WORK_TAG)
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, TimeUnit.SECONDS)
.build()
val operation = WorkManager.getInstance(context)
.enqueueUniqueWork(
Sunique_ID_for_each_job
ExistingWorkPolicy.KEEP,
syncWorkerRequest)
.result
operation.addListener({ Timber.d("RRR added file ${uploadingFile.file.name} ${Thread.currentThread().name}")}, { it.run() })
}
下面是我如何获取它们的日志,它表明文件正在与分配的线程不同的线程上处理:
core.worker.GlobalWorkerFactory: RRR adding factory main
di.module.ApplicationModule: RRR executor thread = sync-worker-thread-0
Activity: RRR calling process sessions
App: RRR config main
Utils$Companion: RRR added file 0.aes pool-14-thread-2
Utils$Companion: RRR added file 1635858822 pool-14-thread-3
CustomWorkerFactory: RRR gettting sync worker on pool-14-thread-1
CustomWorkerFactory: RRR gettting sync worker on pool-14-thread-2
SyncWorker: RRR START sync file 0.aes on thread DefaultDispatcher-worker-1
SyncWorker: RRR START sync file 1635858822 on thread DefaultDispatcher-worker-4
SyncWorker: RRR START sync file 0.aes on thread DefaultDispatcher-worker-3
由于我已经明确定义了 1 个线程并且我成功地将我的线程的配置传递给 GlobalWorkerFactory,所以它不应该尊重第一个日志中看到的线程吗?即:sync-worker-thread-0
我看到其他帖子建议只APPEND
向一名工人工作,但我认为这不是它的用途。即便如此,我指定的线程也不是用于有或没有 APPEND 的工作。
解决方案
来自有关工人的 Android 文档:Doc
注意 CoroutineWorker.doWork() 是一个挂起函数。与 Worker 不同,此代码不会在您的配置中指定的 Executor 上运行。相反,它默认为 Dispatchers.Default。您可以通过提供自己的 CoroutineContext 来自定义它。在上面的示例中,您可能希望在 Dispatchers.IO 上执行此工作,如下所示:
class CoroutineDownloadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
withContext(Dispatchers.IO) {
val data = downloadSynchronously("https://www.google.com")
saveData(data)
return Result.success()
}
}
}
就我而言,我创建了一个newSingleThreadContext
并将其传递给我的工人。
推荐阅读
- python - 有没有办法解决这个关于 StratifiedShuffleSplit 的错误?
- node.js - 使用 multer 上传文件
- jenkins - 如何卸载 Jenkins MacOS
- kubernetes - 如何在域中公开 Kubernetes minikube 应用程序
- next.js - 为什么Next.js 中的组件无法预取?
- kotlin - 在一个响应中发送多个不同类型的 Flux
- python - 创建的 Pdf 文件引发以下错误,文件响应没有读取属性
- python - 模块 trax.fastmath 是否已弃用?
- c++ - 返回 9x9 网格数组中指定子网格的元素?
- javascript - 将客户端变量添加到 AMP 的 GTM 变量