WorkManagerInitializer需要配置setWorkerFactory以向Worker类注入依赖项。本文档介绍了AppStartup中的workManager初始化,但未提供有关如何配置setWorkerFactory的详细信息。如果有人能提出任何解决方案或变通办法,那将是非常有帮助的。问题是我无法将自己的依赖项注入到workerClass中。下面我有两个场景来解释这个案例:`工作场景#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
<?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>// App合规运行成功,但调用doWork()失败
[1]: https://developer.android.com/topic/libraries/app-startup
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: Could not instantiate com.example.baselib.services.local.work_manager.worker.AppWorker
java.lang.NoSuchMethodException: com.example.baselib.services.local.work_manager.worker.AppWorker.<init> [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)发布于 2021-04-20 00:31:20
对于使用带有androidx.work-* 2.6.0-alpha01或更高版本的Hilt的用户:
从release notes开始,这个版本在内部使用了新的androidx.startup jetpack库。因此,从AndroidManifest.xml中删除WorkManager的默认初始化器的方法发生了一些变化。
如果您在应用程序的其他位置使用androidx.startup,请将old change替换为:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.impl.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>否则,您可以通过将旧更改替换为以下内容来完全禁用androidx.startup:
<!-- If you want to disable androidx.startup completely. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove">
</provider>这样,您的HiltWorker将再次使用您的子类应用程序中的工厂。不幸的是,您将失去延迟启动的(明显)好处。
发布于 2020-09-18 19:00:36
您可以通过使用如下所示的@WorkerInject注释来简单地注入依赖项,并摆脱工厂:
class ExampleWorker @WorkerInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
dependency: YourClassDependency
) : Worker(appContext, workerParams) { ... }然后,让您的Application类实现Configuration.Provider接口,注入一个HiltWorkFactory实例,并将其传递到WorkManager配置中,如下所示:
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}请注意,还必须从AndroidManifest.xml中删除缺省初始值设定项
<application>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
</application>发布于 2021-04-27 05:12:35
我们可以直接从Initializer中使用HiltWorkerFactory。示例如下:
class CustomWorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
val workerFactory = getWorkerFactory(appContext = context.applicationContext)
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(context, config)
return WorkManager.getInstance(context)
}
override fun dependencies(): MutableList<Class<out Initializer<*>>> = mutableListOf()
private fun getWorkerFactory(appContext: Context): HiltWorkerFactory {
val workManagerEntryPoint = EntryPointAccessors.fromApplication(
appContext,
WorkManagerInitializerEntryPoint::class.java
)
return workManagerEntryPoint.hiltWorkerFactory()
}
@InstallIn(SingletonComponent::class)
@EntryPoint
interface WorkManagerInitializerEntryPoint {
fun hiltWorkerFactory(): HiltWorkerFactory
}
}删除应用程序中的HiltWorkerFactory注入。
@HiltAndroidApp
class BaseApp : Application() {
override fun onCreate() {
super.onCreate()
AppInitializer.getInstance(this).initializeComponent(CustomWorkManagerInitializer::class.java)
}
}另外,禁用默认的WorkManager初始化器,并在清单中添加我们的自定义。
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- disable default -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="@string/androidx_startup"
tools:node="remove" />
<!-- enable custom -->
<meta-data
android:name="com.acme.app.initializer.CustomWorkManagerInitializer"
android:value="androidx.startup" />
</provider>https://stackoverflow.com/questions/63951589
复制相似问题