我正在嘗試使用 運行同步作業,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:用于向worker注入一些引數
@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
}
}
}
同步作業執行緒執行一些長時間運行的呼叫:
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
I saw other posts suggesting to just APPEND the work to one worker, but I thought that's not how it's meant to be used. And even then, it's not the thread I specified that is used for the work with or without the APPEND.
uj5u.com熱心網友回復:
來自關于工人的 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并將其傳遞給我的工人。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/354218.html
標籤:android multithreading android-workmanager
上一篇:函式代替靜態實用方法
