本文介绍了HiltWorkerFactory:在AppStartup上配置WorkManagerInitializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 22:25