WorkManager 无法使用自定义配置

问题描述 投票:0回答:1

我正在尝试使用

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 个单线程执行器,其中包含一些特定的

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:用于向工人注入一些参数

@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 getting sync worker on ${Thread.currentThread().name}")
                SyncWorker(appContext, workerParameters, api)
            }
            else ->
                null
        }
    }
}

同步工作线程执行一些长时间运行的调用:


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 getting sync worker on pool-14-thread-1
CustomWorkerFactory: RRR getting 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 multithreading android-workmanager
1个回答
1
投票

来自有关工人的 Android 文档:Doc

注意 CoroutineWorker.doWork() 是一个挂起函数。与 Worker 不同,此代码不会在配置中指定的执行器上运行。相反,它默认为 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
并将其传递给我的工人。

© www.soinside.com 2019 - 2024. All rights reserved.