当客户端调用 WorkManager.initialize() 时,WorkManager 无法在库中工作

apa*_*luk 4 android android-workmanager

我正在编写一个使用 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)
Run Code Online (Sandbox Code Playgroud)

在我的 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())
Run Code Online (Sandbox Code Playgroud)

当调用此方法时,我的库中的 WorkManager 未按预期工作。doWork方法不在 my 上调用UploadTripWorker,但在 client 提供的工作线程上执行myWorkerFactory

从我的角度来看,它WorkManager在库中不可用,因为它是单例,有人可以通过initialize方法更改其行为。但我希望我错了。

我有什么办法可以解决这个问题吗?当然,我不能告诉我所有的客户不要使用WorkManager.initialize()方法。

pfm*_*ggi 5

WorkManager v2.1 引入了DelegatingWorkerFactory可以在这些情况下提供帮助的类。

它仍然要求应用程序开发人员以正确的方式实现它,正如您所说的 WorkManager 是一个单例。

关键点是,如果应用程序需要自定义初始化和自定义 WorkerFactory,则应使用 a DelegatingWorkerFactory,然后将其自己的 WorkerFactory 添加到其中。

这里的关键点是应用程序的 WorkerFactory 应该检查工作器类名称以确保它是正确的(通常在构造函数中注入一些参数)。如果类名不是应用程序所期望的名称,它只会返回 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,应用程序需要将此 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)
}
Run Code Online (Sandbox Code Playgroud)

在应用程序课程中,您有:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)