Android 工作管理器:“无法实例化 Worker”

Posted

技术标签:

【中文标题】Android 工作管理器:“无法实例化 Worker”【英文标题】:Android Work Manager: "Could not instantiate Worker" 【发布时间】:2019-03-10 11:08:27 【问题描述】:

我已按照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

谢谢!

【问题讨论】:

【参考方案1】:

我有同样的问题。对我来说问题的原因是我的 Worker 类是一个嵌套类。当我把它变成一个独立的类时,它就起作用了。

【讨论】:

这也解决了我的问题。没有添加 proguard 排除项。 谢谢,拯救了我的一天!仅限独立班!但是有什么区别呢?【参考方案2】:

这是带有 WorkManager 1.0.0-alpha09 的 known issue,已标记为 alpha10 的固定。

作为一种解决方法,您可以将以下行添加到您的 proguard 配置中:

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

【讨论】:

@ianhanniballake 所以......即使你不使用它也需要添加proguard限制? 我在 1.0.0-beta01 中遇到了同样的问题,而且我的构造函数(我的自定义工作者)似乎是包私有的。为了让工作经理工作,它需要公开。我公开了构造函数,它就像一个魅力。 在我的例子中,我将 class 作为默认修饰符,我将其公开并且有效。 在 android.arch.work:work-runtime:1.0.1 (Android Emulator 9.0) 上仍然出现此异常。你升级到1.0.1了吗? @ianhanniballake 2.2.0 中的相同异常【参考方案3】:

我在稳定版 1.0.0 中遇到了这个问题,我通过公开我的工人阶级来解决这个问题。

class MyWorker extends Worker ... > public class MyWorker extends Worker ...

【讨论】:

【参考方案4】:

如果您使用按需初始化和 Dagger 注入整个配置,请确保通过在 AndroidManifest 中添加以下提供程序来删除 WorkManager 默认初始化,如pull request 所建议的那样。这是唯一对我有帮助的事情。更多详情,请查看blog。

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

【讨论】:

非常有帮助。更多解释可以看官方文档developer.android.com/topic/libraries/architecture/workmanager/… 我升级到 2.6,默认初始化以不同的方式删除,这对我来说是个问题【参考方案5】:

对我来说问题是我的 kotlin 类的构造函数:

错误

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

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

【讨论】:

这是最正确的答案。在 WorkManager 代码的深处,有一个 WorkerFactory 接口的实现,它根据上下文 && workerParams 创建一个 Worker。【参考方案6】:

除了Tony's answer:

如果您使用 Kotlin,要记住的另一件事是 Worker 类可以嵌套,但它不能标记为 inner。 p>

我怀疑如果您使用的是 Java,如果您将其标记为 static,您也可以使用嵌套类。但我还没有测试过。

【讨论】:

Add static 是我在 Java 中的解决方案。我只需要将context 存储在Worker 构造函数中即可在doWork() 中重用它。 是的,这个答案适用于嵌套的工人阶级。谢谢。最后也做了和萨尔瓦多一样的事情,而且效果很好。【参考方案7】:

如果您将WorkerHilt 一起使用,那么除了所有other requirements 之外,请确保您是also adding HiltWorkerFactory 到您的Application

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

    @Inject
    lateinit var workerFactory: HiltWorkerFactory

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

【讨论】:

【参考方案8】:

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

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

    <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>
    您需要将 HiltWorkerFactory 注入 Application 类并设置WorkerFactory

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

@Inject
lateinit var workerFactory: HiltWorkerFactory

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

【讨论】:

【参考方案9】:

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

清单文件

<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 清单中设置

【讨论】:

【参考方案10】:

我发现了另一种情况,您可能会遇到NoSuchMethodException

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

kapt.classloaders.cache.size=6

kapt.include.compile.classpath=false

这会对 KAPT 进行积极缓存,导致 WorkManager 未由 hilt 初始化

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

【讨论】:

以上是关于Android 工作管理器:“无法实例化 Worker”的主要内容,如果未能解决你的问题,请参考以下文章

Android开发笔记(一百八十八)工作管理器WorkManager

在 Android 中为定期工作管理器设置初始延迟

Android 工作管理器与服务?

Android 工作管理器:“无法实例化 Worker”

计划的警报管理器无法正常工作 Android

警报管理器不工作... android.app.ReceiverRestrictedContext