Android WorkManager不会触发两个预定的工作程序之一

时间:2019-01-31 08:38:11

标签: android android-workmanager

我在我的应用中安排了两名定期工作的工人,其中一名工人在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,并且网络速度非常好。

2 个答案:

答案 0 :(得分:1)

已解决:WorkManager未触发工作人员

一些调试后解决了问题。如果有人遇到相同问题,请在此处发布。

因此,我一次又一次地取消和排队工人。因此,可以说一个工作人员今天定于上午11.15进行调度,然后我取消并重新排队,因为没有为新排队的工作人员分配11.15 AM的时间段。

相反,当使用11.15 AM插槽时,工作经理只是检查排定的工作人员是否已取消,并且不会触发新排队的工作人员。

这是我们测试的5台设备中有3台的行为。在2台设备上,已正确触发了新入队的工作程序。

现在将溶液:

  1. 删除所有代码安排您的工作人员。

  2. 在应用程序的onCreate()中,首先在pruneWork()上调用WorkManager,以删除所有堆积的已取消工作计划。请记住,该方法返回Operation,这将帮助您检查删除操作是否完成。 在致电pruneWork()之前,您还可以致电cancelAllWorkByTag(),要求所有工作人员清理所有待处理的计划。此方法还返回Operation

  3. 在清除工作经理的日程之后,您现在可以按自己的方式安排PeriodicWorkRequest了。我使用enqueueUniquePeriodicWork()来确保一次仅运行一个worker实例。

现在,我的工作人员每15分钟被正确触发一次。

请注意,当您的设备进入睡眠模式并进入休眠模式时,这15分钟的持续时间将会增加。

您可以使用Stetho库检查工作管理器数据库。 表名是WorkSpec,你会发现你的员工的所有计划。而且,您可以在某个断点处停止应用程序的执行,并在getWorkInfosByTag()上使用WorkManager以获得日程表及其当前状态的列表。

答案 1 :(得分:0)

您所做的一些不正确的事情。

  1. 您正在使用LiveData并对其调用getValue()而不添加观察者。这不会为您提供所需的东西-LiveData永远不会开始跟踪所需的值。请在此处检查LiveData的正确用法:https://developer.android.com/topic/libraries/architecture/livedata

  2. 如果您只想要一种工作类型的特定副本,则应使用enqueueUniqueWork而不是enqueue。

  3. 除非您发现自己确实处于极度糟糕的境地,而您实际上需要删除旧工作人员,否则我建议您不要调用pruneWork()。请参阅文档:https://developer.android.com/reference/androidx/work/WorkManager#pruneWork()