Android 工作经理:"Could not instantiate Worker"

Android Work Manager: "Could not instantiate Worker"

我已经按照 Android Developer's 关于使用 Worker Manager 结构的教程在后台 运行 我的代码,但是任何时候我尝试让我的 worker 入队时它都不会 运行 并且我收到以下错误:

2018-10-04 22:25:47.004 28669-28885/app.package.com.debug E/DefaultWorkerFactory: Could not instantiate app.package.com.MyWorker
    java.lang.NoSuchMethodException: <init> []
        at java.lang.Class.getConstructor0(Class.java:2320)
        at java.lang.Class.getDeclaredConstructor(Class.java:2166)
        at androidx.work.DefaultWorkerFactory.createWorker(DefaultWorkerFactory.java:58)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:180)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
2018-10-04 22:25:47.005 28669-28885/app.package.com.debug E/WorkerWrapper: Could for create Worker app.package.com.MyWorker

我发现这个问题可能与 worker 上的默认构造函数有关,但我已经使用了正确的构造函数而不是已弃用的默认函数。

我的工人声明为:

public class MyWorker extends Worker {

    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        // Doesn't even get called
    }
}

它像这样排队:

WorkManager workManager = WorkManager.getInstance();
if (myWorkerRequest == null) {
    myWorkerRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
            .setConstraints(new Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build())
            .build();
}
WorkStatus workStatus = workManager.getStatusById(myWorkerRequest.getId()).getValue();
if (workStatus == null || !workStatus.getState().isFinished()) {
    workManager.enqueue(myWorkerRequest);
}

我没有发现与示例有任何不同,因此我想了解还有什么可能会影响我的代码导致此崩溃。会不会是 ProGuard 相关的东西?

我的版本是1.0.0-alpha09

谢谢!

这是一个带有 WorkManager 1.0.0-alpha09 的 known issue,已标记为已针对 alpha10 修复。

作为解决方法,您可以将以下行添加到混淆器配置中:

-keepclassmembers class * extends androidx.work.Worker {
    public <init>(android.content.Context,androidx.work.WorkerParameters);
}

我在稳定版 1.0.0 中遇到了这个问题,我通过让我的 worker class public 修复了它。

class MyWorker extends Worker {...} > public class MyWorker extends Worker {...}

我遇到了同样的问题。对我来说,问题的原因是我的 Worker class 是一个嵌套的 class。在我将其设为独立 class 的那一刻,它起作用了。

我的问题是我的 kotlin 的构造函数 class:

错误

class MyWorker(val app: Application, workerParams: WorkerParameters): Worker(app, workerParams)

class MyWorker(val context: Context, workerParams: WorkerParameters): Worker(context, workerParams)

如果您使用按需初始化和 Dagger 来注入整个配置,请确保按照 pull request. This was the only thing which helped me. For more details, check the blog.[=12= 的建议,通过在 AndroidManifest 中添加以下提供程序来删除 WorkManager 默认初始化]

<!-- Remove WorkManager default initialization -->
<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:authorities="${applicationId}.workmanager-init"
    tools:node="remove" />

如果您将 WorkerHilt 一起使用,那么,除了所有 other requirements, make sure you are also adding HiltWorkerFactory 到您的 Application class

@HiltAndroidApp
class App: Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}

除了

如果您使用 Kotlin,要记住的另一件事是 Worker class 可以 嵌套,但它 不能被标记作为 inner.

我怀疑如果您正在使用 Java,如果您将嵌套的 class 标记为 static,您也可以使用它。但是我没有测试过这个。

我遇到了同样的错误然后我意识到添加应用程序启动库解决了我的问题

清单文件

<provider
        android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <meta-data
            android:name="androidx.work.WorkManagerInitializer"
            android:value="androidx.startup"
            tools:node="remove" />
    </provider>

build.gradle.app

 def work_version = "2.6.0"
    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"
    implementation 'androidx.hilt:hilt-work:1.0.0'
    kapt "com.google.dagger:hilt-android-compiler:2.37"

    //app start up
    implementation("androidx.startup:startup-runtime:1.1.0")

我刚刚添加了应用程序启动库并在 Android menifest

中设置

我遇到了同样的问题,我的解决方案在这里

  1. 我更新工作管理器版本 “2.6.0-alpha02” 之前的版本是“2.5.0”
  2. 您需要将带有元数据的提供商添加到清单中。

    <provider
      android:name="androidx.startup.InitializationProvider"
      android:authorities="${applicationId}.androidx-startup"
      android:exported="false"
      tools:node="merge">
      <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
    </provider>

  1. 您需要将 HiltWorkerFactory 注入应用程序 class 和 setWorkerFactory

@HiltAndroidApp
class App: Application(), Configuration.Provider {

@Inject
lateinit var workerFactory: HiltWorkerFactory

override fun getWorkManagerConfiguration() =
    Configuration.Builder()
        .setWorkerFactory(workerFactory)
        .build()
}

我发现了另一种情况,您可能 运行 进入 NoSuchMethodException

如果您启用了这些 gradle 属性:

kapt.classloaders.cache.size=6

kapt.include.compile.classpath=false

这会主动缓存 KAPT,导致 WorkManager 未被 hilt

初始化

我删除了这些属性并且它起作用了。