Android WorkManager 没有触发两个预定工作程序之一
Android WorkManager doesn't trigger one of the two scheduled workers
我在我的应用程序中安排了两个定期工作人员,其中一个工作人员在 24 小时后重复,另一个在 15 分钟后重复。
最初在全新安装时一切正常,但几天后我在 2 台设备(共 5 台)上遇到问题。
24 小时工作人员被正确触发,但 15 分钟工作人员根本没有被触发。我现在已经监控了 24 小时。
我通过 Stetho 查看了 workmanager 的数据库,看到一些 24 小时工作人员的条目和 0 个 15 分钟工作人员的条目。我正在查看 WorkSpec
table.
我通过 Android studio 进行了调试,在使用 getWorkInfosByTag()
查询 WorkManager 后,我得到了 15 分钟工作人员的 80 个对象列表,其中 79 个处于 CANCELED
状态,一个处于 CANCELED
状态在 ENQUEUED
状态。
显然,取消的工人没有添加到数据库中?
我没有在 Google 中找到任何解释取消工作人员场景的文档。
我正在使用 1.0.0-beta03
版本的工作运行时。
此外,我不会终止应用程序或做任何有趣的事情。该应用程序在后台 运行,并且没有被杀死。
设备是 Mi A2 (Android 9), Redmi Note 4(Android 7).
我需要了解为什么 worker 被取消,有没有更好的调试方法?任何指点都会有所帮助和赞成!
谢谢。
Edit1:发布代码以安排两个工作人员。
24 小时周期性工人:
public static synchronized void scheduleWork() {
checkPreviousWorkerStatus();
if (isWorking()) {
Log.i("AppDataCleanupWorker", "Did not schedule data cleanup work; already running.");
return;
}
if (lastWorkId != null) {
WorkManager.getInstance().cancelAllWorkByTag("AppDataCleanupWorker");
lastWorkId = null;
}
Constraints constraints = new Constraints.Builder()
.setRequiresCharging(true)
.build();
PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
.Builder(AppDataCleanupWorker.class, 24, TimeUnit.HOURS)
.addTag("AppDataCleanupWorker")
.setConstraints(constraints);
PeriodicWorkRequest workRequest = builder.build();
lastWorkId = workRequest.getId();
WorkManager.getInstance().enqueue(workRequest);
List<WorkInfo> workInfos = WorkManager.getInstance()
.getWorkInfosByTagLiveData("AppDataCleanupWorker")
.getValue();
if (workInfos != null && workInfos.size() > 1) {
throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
}
}
15 分钟周期性工作人员:
public static synchronized void scheduleWork() {
checkPreviousWorkerStatus();
if (isWorking) {
Log.i("ImageUploadWorker", "Did not schedule image upload work; already running.");
return;
}
if (lastWorkId != null) {
WorkManager.getInstance().cancelAllWorkByTag("ImageUploadWorker");
lastWorkId = null;
}
Constraints constraints = new Constraints.Builder()
.setRequiresBatteryNotLow(true)
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest.Builder builder =
new PeriodicWorkRequest.Builder(ImageUploadWorker.class, 15,
TimeUnit.MINUTES)
.addTag("ImageUploadWorker")
.setConstraints(constraints);
PeriodicWorkRequest workRequest = builder.build();
lastWorkId = workRequest.getId();
WorkManager.getInstance().enqueue(workRequest);
List<WorkInfo> workInfos = WorkManager.getInstance()
.getWorkInfosByTagLiveData("ImageUploadWorker").getValue();
if (workInfos != null && workInfos.size() > 1) {
throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
}
}
注意:设备已联网且网速不错
已解决:Worker 未被 WorkManager 触发
经过一些调试解决了问题。如果有人遇到同样的问题,请在此发帖。
所以,我一次又一次地取消和排队工人。所以假设一个工作人员被安排在今天上午 11 点 15 分,然后我取消并再次排队,上午 11 点 15 分的时段没有分配给新入队的工作人员。
相反,当使用 11.15 AM 时段时,工作管理器仅检查已取消安排的工作人员,而不会触发新排队的工作人员。
这是我们测试的 5 台设备中的 3 台的行为。在 2 台设备上,新排队的工作人员被正确触发。
现在的解决方案:
删除所有代码以安排您的工作人员。
在您的应用程序的 onCreate()
中,首先在 WorkManager
上调用 pruneWork()
以删除所有堆积的已取消工作人员计划。记住方法 returns Operation
这将帮助您检查删除是否完成。
在调用 pruneWork()
之前,您还可以为所有工作人员调用 cancelAllWorkByTag()
来清理所有待处理的计划。此方法还 returns 一个 Operation
.
清除工作管理器日程安排后,您现在可以按照自己的方式安排 PeriodicWorkRequest
。我使用 enqueueUniquePeriodicWork()
来确保一次只有一个 worker 实例是 运行。
现在,我的工作器每 15 分钟正确触发一次。
请注意,当您的设备休眠并进入休眠模式时,这 15 分钟的持续时间将会增加。
您可以使用 Stetho 库检查工作管理器数据库。
table 名称是 WorkSpec
,您可以在其中找到员工的所有日程安排。您可以在某个断点处停止应用程序执行,并在 WorkManager
上使用 getWorkInfosByTag()
来获取计划列表及其当前状态。
你做的一些事情是不正确的。
您正在使用 LiveData 并在其上调用 getValue() 而未添加观察者。这不会给你你正在寻找的东西——LiveData 永远不会开始跟踪你想要的值。请在此处查看正确的 LiveData 用法:https://developer.android.com/topic/libraries/architecture/livedata
如果您只想要一种工作的一个特定副本,您应该使用 enqueueUniqueWork 而不是 enqueue。
除非你发现自己处在一个非常糟糕的情况下,你真的需要移除老工人,否则我建议你不要调用pruneWork()。请参阅文档:https://developer.android.com/reference/androidx/work/WorkManager#pruneWork()
我在我的应用程序中安排了两个定期工作人员,其中一个工作人员在 24 小时后重复,另一个在 15 分钟后重复。
最初在全新安装时一切正常,但几天后我在 2 台设备(共 5 台)上遇到问题。 24 小时工作人员被正确触发,但 15 分钟工作人员根本没有被触发。我现在已经监控了 24 小时。
我通过 Stetho 查看了 workmanager 的数据库,看到一些 24 小时工作人员的条目和 0 个 15 分钟工作人员的条目。我正在查看 WorkSpec
table.
我通过 Android studio 进行了调试,在使用 getWorkInfosByTag()
查询 WorkManager 后,我得到了 15 分钟工作人员的 80 个对象列表,其中 79 个处于 CANCELED
状态,一个处于 CANCELED
状态在 ENQUEUED
状态。
显然,取消的工人没有添加到数据库中?
我没有在 Google 中找到任何解释取消工作人员场景的文档。
我正在使用 1.0.0-beta03
版本的工作运行时。
此外,我不会终止应用程序或做任何有趣的事情。该应用程序在后台 运行,并且没有被杀死。
设备是 Mi A2 (Android 9), Redmi Note 4(Android 7).
我需要了解为什么 worker 被取消,有没有更好的调试方法?任何指点都会有所帮助和赞成!
谢谢。
Edit1:发布代码以安排两个工作人员。
24 小时周期性工人:
public static synchronized void scheduleWork() {
checkPreviousWorkerStatus();
if (isWorking()) {
Log.i("AppDataCleanupWorker", "Did not schedule data cleanup work; already running.");
return;
}
if (lastWorkId != null) {
WorkManager.getInstance().cancelAllWorkByTag("AppDataCleanupWorker");
lastWorkId = null;
}
Constraints constraints = new Constraints.Builder()
.setRequiresCharging(true)
.build();
PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
.Builder(AppDataCleanupWorker.class, 24, TimeUnit.HOURS)
.addTag("AppDataCleanupWorker")
.setConstraints(constraints);
PeriodicWorkRequest workRequest = builder.build();
lastWorkId = workRequest.getId();
WorkManager.getInstance().enqueue(workRequest);
List<WorkInfo> workInfos = WorkManager.getInstance()
.getWorkInfosByTagLiveData("AppDataCleanupWorker")
.getValue();
if (workInfos != null && workInfos.size() > 1) {
throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
}
}
15 分钟周期性工作人员:
public static synchronized void scheduleWork() {
checkPreviousWorkerStatus();
if (isWorking) {
Log.i("ImageUploadWorker", "Did not schedule image upload work; already running.");
return;
}
if (lastWorkId != null) {
WorkManager.getInstance().cancelAllWorkByTag("ImageUploadWorker");
lastWorkId = null;
}
Constraints constraints = new Constraints.Builder()
.setRequiresBatteryNotLow(true)
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest.Builder builder =
new PeriodicWorkRequest.Builder(ImageUploadWorker.class, 15,
TimeUnit.MINUTES)
.addTag("ImageUploadWorker")
.setConstraints(constraints);
PeriodicWorkRequest workRequest = builder.build();
lastWorkId = workRequest.getId();
WorkManager.getInstance().enqueue(workRequest);
List<WorkInfo> workInfos = WorkManager.getInstance()
.getWorkInfosByTagLiveData("ImageUploadWorker").getValue();
if (workInfos != null && workInfos.size() > 1) {
throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
}
}
注意:设备已联网且网速不错
已解决:Worker 未被 WorkManager 触发
经过一些调试解决了问题。如果有人遇到同样的问题,请在此发帖。
所以,我一次又一次地取消和排队工人。所以假设一个工作人员被安排在今天上午 11 点 15 分,然后我取消并再次排队,上午 11 点 15 分的时段没有分配给新入队的工作人员。
相反,当使用 11.15 AM 时段时,工作管理器仅检查已取消安排的工作人员,而不会触发新排队的工作人员。
这是我们测试的 5 台设备中的 3 台的行为。在 2 台设备上,新排队的工作人员被正确触发。
现在的解决方案:
删除所有代码以安排您的工作人员。
在您的应用程序的
onCreate()
中,首先在WorkManager
上调用pruneWork()
以删除所有堆积的已取消工作人员计划。记住方法 returnsOperation
这将帮助您检查删除是否完成。 在调用pruneWork()
之前,您还可以为所有工作人员调用cancelAllWorkByTag()
来清理所有待处理的计划。此方法还 returns 一个Operation
.清除工作管理器日程安排后,您现在可以按照自己的方式安排
PeriodicWorkRequest
。我使用enqueueUniquePeriodicWork()
来确保一次只有一个 worker 实例是 运行。
现在,我的工作器每 15 分钟正确触发一次。
请注意,当您的设备休眠并进入休眠模式时,这 15 分钟的持续时间将会增加。
您可以使用 Stetho 库检查工作管理器数据库。
table 名称是 WorkSpec
,您可以在其中找到员工的所有日程安排。您可以在某个断点处停止应用程序执行,并在 WorkManager
上使用 getWorkInfosByTag()
来获取计划列表及其当前状态。
你做的一些事情是不正确的。
您正在使用 LiveData 并在其上调用 getValue() 而未添加观察者。这不会给你你正在寻找的东西——LiveData 永远不会开始跟踪你想要的值。请在此处查看正确的 LiveData 用法:https://developer.android.com/topic/libraries/architecture/livedata
如果您只想要一种工作的一个特定副本,您应该使用 enqueueUniqueWork 而不是 enqueue。
除非你发现自己处在一个非常糟糕的情况下,你真的需要移除老工人,否则我建议你不要调用pruneWork()。请参阅文档:https://developer.android.com/reference/androidx/work/WorkManager#pruneWork()