如何解决HiltWorkerFactory:在AppStartup上配置WorkManagerInitializer
WorkManagerInitializer
需要配置setWorkerFactory以将依赖项注入到Worker
类中。 document解释了有关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>
//应用符合并成功运行,但是无法调用doWork()
未使用在AppStartup上定义的WorkManagerInitializer调用AppWorker类的dowork()方法。这是logcat中的错误:
2020-09-24 19:38:41.811 23803-23863 / com.example.baseapp E / WM-WorkerFactory:无法实例化com.example.baselib.services.local.work_manager.worker.AppWorker java.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)
解决方法
对于使用 androidx.work-*
版本 2.6.0-alpha01
或更高版本的刀柄的人:
从 release notes 起,此版本开始在内部使用新的 androidx.startup
jetpack 库。
因此,从 WorkManager
中删除 AndroidManifest.xml
的默认初始值设定项的方式发生了一些变化。
如果您在应用的其他地方使用 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
将再次使用子类应用中的工厂。不幸的是,您将失去延迟启动的(明显的)好处。
您可以使用如下所示的@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>
参考:Hilt and Jetpack Integrations
,我们可以直接从 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>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。