【问题标题】:Android Work Manager: "Could not instantiate Worker"Android 工作管理器:“无法实例化 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

谢谢!

【问题讨论】:

    标签: android androidx android-workmanager


    【解决方案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" />
      

      【讨论】:

      【解决方案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】:

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

        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 注入 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 初始化

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-02-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-04
              • 1970-01-01
              相关资源
              最近更新 更多