我在我的应用中安排了两名定期工作的工人,其中一名工人在24小时后重复一次,另一名在15分钟后重复一次。
最初,通过全新安装可以正常工作,但是几天后,我在2台设备(5台设备)中遇到了问题。 正确触发了24小时工作人员,但完全没有触发15分钟的工作人员。我已经对此进行了24小时的监控。
我通过Stetho查看了工作经理的数据库,看到一些24小时工作人员的条目和0个15分钟工作人员的条目。我正在查看WorkSpec
表。
我通过Android Studio进行了调试,并使用getWorkInfosByTag()
查询WorkManager后,我得到了一个15分钟的工作人员的80个对象的列表,其中79个处于CANCELED
状态,一个处于ENQUEUED
状态状态。
那么显然取消的工作人员不会添加到数据库中吗?
我从Google找不到任何文档来说明取消工作人员的情况。
我正在使用1.0.0-beta03
版的工作运行时。
另外,我不会杀死应用程序或做任何有趣的事情。该应用程序在后台运行,没有被杀死。
设备为Mi A2(Android 9),Redmi Note 4(Android 7)。
我需要了解为什么取消该工作程序,还有什么更好的方法来调试它?任何指针都将是有帮助的,并且会被批评!
谢谢。
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.");
}
}
注意:设备已连接到Internet,并且网络速度非常好。
答案 0 :(得分:1)
一些调试后解决了问题。如果有人遇到相同问题,请在此处发布。
因此,我一次又一次地取消和排队工人。因此,可以说一个工作人员今天定于上午11.15进行调度,然后我取消并重新排队,因为没有为新排队的工作人员分配11.15 AM的时间段。
相反,当使用11.15 AM插槽时,工作经理只是检查排定的工作人员是否已取消,并且不会触发新排队的工作人员。
这是我们测试的5台设备中有3台的行为。在2台设备上,已正确触发了新入队的工作程序。
现在将溶液:
删除所有代码安排您的工作人员。
在应用程序的onCreate()
中,首先在pruneWork()
上调用WorkManager
,以删除所有堆积的已取消工作计划。请记住,该方法返回Operation
,这将帮助您检查删除操作是否完成。
在致电pruneWork()
之前,您还可以致电cancelAllWorkByTag()
,要求所有工作人员清理所有待处理的计划。此方法还返回Operation
。
在清除工作经理的日程之后,您现在可以按自己的方式安排PeriodicWorkRequest
了。我使用enqueueUniquePeriodicWork()
来确保一次仅运行一个worker实例。
现在,我的工作人员每15分钟被正确触发一次。
请注意,当您的设备进入睡眠模式并进入休眠模式时,这15分钟的持续时间将会增加。
您可以使用Stetho库检查工作管理器数据库。
表名是WorkSpec
,你会发现你的员工的所有计划。而且,您可以在某个断点处停止应用程序的执行,并在getWorkInfosByTag()
上使用WorkManager
以获得日程表及其当前状态的列表。
答案 1 :(得分:0)
您所做的一些不正确的事情。
您正在使用LiveData并对其调用getValue()而不添加观察者。这不会为您提供所需的东西-LiveData永远不会开始跟踪所需的值。请在此处检查LiveData的正确用法:https://developer.android.com/topic/libraries/architecture/livedata
如果您只想要一种工作类型的特定副本,则应使用enqueueUniqueWork而不是enqueue。
除非您发现自己确实处于极度糟糕的境地,而您实际上需要删除旧工作人员,否则我建议您不要调用pruneWork()。请参阅文档:https://developer.android.com/reference/androidx/work/WorkManager#pruneWork()