问题描述
WorkManagerInitializer
要求配置setWorkerFactory以将依赖项注入到 Worker
类.文档解释了有关AppStartup上的workManager初始化的信息,但未提供有关如何配置setWorkerFactory.如果有什么可以建议任何解决方案或解决方法的话,那将非常有帮助.问题是我无法将自己的依赖项注入workerClass中.我在下面包括两种情况来说明这种情况:工作场景1:
WorkManagerInitializer
requires to configure setWorkerFactory to inject dependencies to the Worker
class. The document explains about workManager Initialization at AppStartup, but does not provide any insights on how to configure setWorkerFactory. If any could suggest any solutions or workaround, that'll be greatly helpful.The problem is that I am unable to inject my own dependencies into the workerClass. I have include two scenarios below to explain the case:`Working Scenario #1:
//此调用工作正常.
class AppWorker @WorkerInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : Worker(context, workerParams) {
companion object {
val workType = "WorkType"
}
override fun doWork(): Result {
return Result.success()
}
}
失败的方案2:
// Initializes WorkManager.
class WorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
// How to get workFactory required for configuration.
var workerFactory: HiltWorkerFactory? = null
val configuration = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(context, configuration)
return WorkManager.getInstance(context)
}
override fun dependencies(): List<Class<out Initializer<*>>> {
// No dependencies on other libraries.
return emptyList()
}
}
@HiltAndroidApp
class BaseApp: Application(),Configuration.Provider{
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
init {
Thread.setDefaultUncaughtExceptionHandler(ThreadExceptionalHandler())
}
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(DebugTree())
}
}
}
Manifest.xml
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.baseapp">
<application
android:name="com.example.baseapp.startup.BaseApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApp"
>
<activity android:name="com.example.baseapp.gui.activities.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data android:name="com.example.baseapp.startup.AppServicesInitializer"
android:value="androidx.startup" />
</provider>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove"/>
</application>
</manifest>
//应用符合并成功运行,但是无法调用doWork()
// App complies and runs successfully, but fails to call doWork()
未使用在AppStartup上定义的WorkManagerInitializer调用AppWorker类的dowork()方法.这是logcat中的错误:
The AppWorker class dowork() method is not getting called with WorkManagerInitializer defined at AppStartup. Here is the error in logcat:
2020-09-24 19:38:41.811 23803-23863/com.example.baseapp E/WM-WorkerFactory:无法实例化com.example.baselib.services.local.work_manager.worker.AppWorkerjava.lang.NoSuchMethodException:com.example.baselib.services.local.work_manager.worker.AppWorker.[class android.content.Context,class androidx.work.WorkerParameters]在java.lang.Class.getConstructor0(Class.java:2332)在java.lang.Class.getDeclaredConstructor(Class.java:2170)在androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)在androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)在androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)在androidx.work.impl.utils.SerialExecutor $ Task.run(SerialExecutor.java:91)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:641)在java.lang.Thread.run(Thread.java:923)
2020-09-24 19:38:41.811 23803-23863/com.example.baseapp E/WM-WorkerFactory: Could not instantiate com.example.baselib.services.local.work_manager.worker.AppWorkerjava.lang.NoSuchMethodException: com.example.baselib.services.local.work_manager.worker.AppWorker. [class android.content.Context, class androidx.work.WorkerParameters]at java.lang.Class.getConstructor0(Class.java:2332)at java.lang.Class.getDeclaredConstructor(Class.java:2170)at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)at java.lang.Thread.run(Thread.java:923)
推荐答案
您可以使用如下所示的 @WorkerInject
批注简单地注入依赖项并摆脱工厂:
You can simply inject dependencies by using @WorkerInject
annotation like below and get rid of your factory:
class ExampleWorker @WorkerInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
dependency: YourClassDependency
) : Worker(appContext, workerParams) { ... }
然后,让您的 Application
类实现 Configuration.Provider
接口,注入 HiltWorkFactory
的实例,并将其传递给 WorkManager
配置如下:
Then, have your Application
class implement the Configuration.Provider
interface, inject an instance of HiltWorkFactory
, and pass it into the WorkManager
configuration as follows:
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
请注意,您还必须从 AndroidManifest.xml
中删除默认的初始化程序:
Note that you also must remove the default initializer from the AndroidManifest.xml
:
<application>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
</application>
参考: Hilt和Jetpack集成
这篇关于HiltWorkerFactory:在AppStartup上配置WorkManagerInitializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!