我正在编写一个使用WorkManager的Android库。在代码中的某处,我这样调用:
val uploadTripRequest = OneTimeWorkRequest.Builder(UploadTripWorker::class.java)
.setConstraints(someConstraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(WORKER_NAME, ExistingWorkPolicy.REPLACE, uploadTripRequest)
在我的build.gradle中,我有:
implementation 'androidx.work:work-runtime:2.2.0'
通常,一切正常。客户端应用程序调用https://developer.android.com/reference/kotlin/androidx/work/WorkManager.html#initialize时会出现问题,例如:
WorkManager.initialize(context, Configuration.Builder().setWorkerFactory(myWorkerFactory).build())
调用此命令时,我的库中的WorkManager无法正常工作。我的
doWork
上没有调用UploadTripWorker
方法,但是在客户端的myWorkerFactory
提供的工作程序上执行。在我看来,
WorkManager
在库中不可用,因为它是单例,并且有人可以通过initialize
方法更改其行为。但我希望我错了。有什么办法可以解决这个问题?当然,我不能对所有客户说不使用
WorkManager.initialize()
方法。 最佳答案
WorkManager v2.1引入了DelegatingWorkerFactory
类,在这些情况下可以提供帮助。
正如您所说的WorkManager是单例的那样,仍然需要应用程序开发人员以正确的方式实现它。
关键是,如果应用程序需要自定义初始化和自定义WorkerFactory,则应使用DelegatingWorkerFactory
,然后使用add它是它自己的WorkerFactory。
这里的关键点是应用程序的WorkerFactory应该检查worker类的名称,以确保它是正确的名称(通常在构造函数中注入一些参数)。如果类名不是应用程序所期望的名称,则它可以仅返回null,而DelegatingWorkerFactory
将注意找到要实例化的正确的工人类。
类似于(在应用程序代码中)的内容:
class MyWorkerFactory(
private val myInjectedParam: InjectedParam
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
return when (workerClassName) {
MyWorker::class.java.name ->
MyWorker(appContext, workerParameters, myInjectedParam)
else ->
// Return null, so that the base class can delegate to the default WorkerFactory.
null
}
}
}
然后,应用程序需要使用以下命令将此WorkerFactory添加到已设置为自定义WorkerFactory的DelegatingWorkerFactory中:
private fun initializeWorkManager (myInjectedParam: MyInjectedParam): WorkManager
{
val appContext = getApplication<MyApplication>()
val factory = appContext.workManagerConfiguration.workerFactory
as DelegatingWorkerFactory
factory.addFactory(MyWorkerFactory(myInjectedParam))
return WorkManager.getInstance(appContext)
}
在应用程序类中,您可以:
class MainApplication : Application(), Configuration.Provider {
val delegatingWorkerFactory: DelegatingWorkerFactory
// Setup custom configuration for WorkManager with a DelegatingWorkerFactory
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.INFO)
.setWorkerFactory(delegatingWorkerFactory)
.build()
}
}