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
,您也可以使用嵌套类。但我还没有测试过。
【讨论】:
Addstatic
是我在 Java 中的解决方案。我只需要将context
存储在Worker
构造函数中即可在doWork()
中重用它。
是的,这个答案适用于嵌套的工人阶级。谢谢。最后也做了和萨尔瓦多一样的事情,而且效果很好。【参考方案7】:
如果您将Worker
与Hilt
一起使用,那么除了所有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”的主要内容,如果未能解决你的问题,请参考以下文章