使用 WorkManager 进行定期的每日工作请求

18
如何正确使用Android Jetpack的新WorkManager来安排每天一次的周期性工作,该工作应每天执行一次且仅一次?
想法是使用WorkManager检查是否已存在具有给定标签的工作,并在没有时启动新的周期性工作。
我尝试使用以下方法来实现:
public static final String CALL_INFO_WORKER = "Call worker";

...

WorkManager workManager = WorkManager.getInstance();
List<WorkStatus> value = workManager.getStatusesByTag(CALL_INFO_WORKER).getValue();
if (value == null) {
    WorkRequest callDataRequest = new PeriodicWorkRequest.Builder(CallInfoWorker.class,
                24, TimeUnit.HOURS, 3, TimeUnit.HOURS)
                .addTag(CALL_INFO_WORKER)
                .build();
    workManager.enqueue(callDataRequest);
}

但是value始终为空,即使我在WorkerdoWork()方法内设置断点(所以它肯定正在进行中),并从另一个线程检查工作状态。

3个回答

18

现在您可以使用enqueueUniquePeriodicWork方法。该方法是在WorkManager的1.0.0-alpha03版本中添加的。


@atasoyh您有关于它的任何bug报告可以提供给我阅读吗? - stefana
@stefana https://github.com/googlecodelabs/android-workmanager/issues/28 - atasoyh
alpha10已经发布。 - Al-Amin
这在Oreo和Lollipop上不起作用,有什么帮助吗? - ralphgabb

16

您正在寻找enqueueUniquePeriodicWork

此方法允许您排队一个唯一命名的PeriodicWorkRequest,其中特定名称的一个PeriodicWorkRequest只能在同一时间处于活动状态。例如,您可能只想要一个同步操作处于活动状态。如果有一个待处理的操作,您可以选择让它运行或用新的工作替换它。

示例代码

public static final String TAG_MY_WORK = "mywork";

public static void scheduleWork(String tag) {
    PeriodicWorkRequest.Builder photoCheckBuilder =
            new PeriodicWorkRequest.Builder(WorkManagerService.class, 1, TimeUnit.DAYS);
    PeriodicWorkRequest request = photoCheckBuilder.build();
    WorkManager.getInstance().enqueueUniquePeriodicWork(tag, ExistingPeriodicWorkPolicy.KEEP , request);
}

有两种ExistingPeriodicWorkPolicy

KEEP

如果存在相同唯一名称的挂起任务,则不执行任何操作。

REPLACE

如果存在相同唯一名称的挂起任务,则取消并删除它。


谢谢,当问题被提出时,那不是API的一部分。当它出现时,已经给出了解决方案的答案。 - Gaket
我尝试使用上述周期性编程。它只能在一次运行中正常工作,而在下一个日期更改时无法触发。我已经尝试了2.3.0-beta02版本。 - harikrishnan

1
最终,我明白了问题在于使用LiveData的方式。因为没有观察者,所以里面没有值。
仅使用PeriodicWork的问题在于它不能确保您想要执行的工作的唯一性。换句话说,可能会有许多工作同时处于活动状态,比您需要的次数更频繁地触发。

1
我还没有能够进行24小时的检查,但我的15分钟测试表现良好,即使在手机重新启动后也是如此。 - Gaket
PeriodicWorkRequest.Builder myWorkBuilder = new PeriodicWorkRequest.Builder(MyWorker.class, 5, TimeUnit.SECONDS,5,TimeUnit.SECONDS); 这段代码会在前5秒内持续运行,之后就不再执行了。 - Lavanya Velusamy
PeriodicWorkRequest.Builder myWorkBuilder = new PeriodicWorkRequest.Builder(MyWorker.class, 20, TimeUnit.MINUTES); 我已经这样写了,但它并没有按时运行。 - Lavanya Velusamy
请回答这个问题:https://dev59.com/ElUL5IYBdhLWcg3waHRw - Lavanya Velusamy
@LavanyaVelusamy 我也有同样的问题,请问你是否找到了解决方案还是这个问题仍存在?我创建了一个20分钟的定期工作请求,但它只在我启动应用程序时运行一次。 - ysfcyln
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接