用于在后台运行日常任务的 Android WorkManager api
Posted
技术标签:
【中文标题】用于在后台运行日常任务的 Android WorkManager api【英文标题】:Android WorkManager api for running daily task in Background 【发布时间】:2018-10-29 03:46:03 【问题描述】:即使应用程序关闭,我也需要每天在后台调用一个 API。我看过 WorkManager API。对于我的场景,我尝试了 PeriodicWorkRequest 但不幸的是,它没有达到我的预期结果。我所做的是我在 Application 类中使用了这段代码
PeriodicWorkRequest.Builder myWorkBuilder =
new PeriodicWorkRequest.Builder(MyWorker.class, 24,
TimeUnit.HOURS);
PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance().enqueue(myWork);
但应用程序第一次打开时重复运行11次,24小时后不再运行。请各位大神帮我解决一下。
【问题讨论】:
【参考方案1】:如果您想确保您的PeriodicWorkRequest
不会被多次创建,您可以使用WorkManager.enqueueUniquePeriodicWork
方法来安排您的工作人员:
此方法允许您将唯一命名的 PeriodicWorkRequest 排入队列,其中一次只能激活一个特定名称的 PeriodicWorkRequest。例如,您可能只希望一个同步操作处于活动状态。如果有一个待处理,您可以选择让它运行或用您的新工作替换它。
例如:
PeriodicWorkRequest.Builder myWorkBuilder =
new PeriodicWorkRequest.Builder(MyWorker.class, 24, TimeUnit.HOURS);
PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance()
.enqueueUniquePeriodicWork("jobTag", ExistingPeriodicWorkPolicy.KEEP, myWork);
【讨论】:
onetimerequest 是否也有类似的选项?有时,相同的工作会被并行调用两次。如何阻止这种情况? @Aram 你试过beginUniqueWork(...)吗? 是的,我试过了,但我们需要使用 Workcontinuation 对象。我不知道那个选项是否更昂贵。有什么想法吗? 根据最佳实践我们应该在应用程序的哪个位置配置作业? 上面的代码 sn-p 在具有 android Pie (9) 的设备 (OnePlus 4T) 中启动PeriodicWorkRequest
,不工作,WorkManager 没有将 Worker 排队。因为我也在这里寻求有关 *** 的帮助:***.com/questions/56697105/…【参考方案2】:
我认为存在三个问题。
1) 每次 enqueue
myWork
到 WorkManager
实例时,您都会创建一个新的周期性工作。
试试看,MyWorker.class
的 doWork()
方法中的逻辑第一次运行一次,第二次运行两次。您很可能向工作管理器添加了 11 个作品,这就是您上次检查时它运行 11 次的原因。如果您创建新作品并将其添加到工作管理器中,则myWork
运行的次数会增加。
与 Job Scheduler 类似,您必须先检查 Work 是否存在,然后才能将其添加到 Work Manager。
示例代码:
final WorkManager workManager = WorkManager.getInstance();
final LiveData<List<WorkStatus>> statusesByTag = workManager
.getStatusesByTag(TAG_PERIODIC_WORK_REQUEST);
statusesByTag.observe(this, workStatuses ->
if (workStatuses == null || workStatuses.size() == 0)
Log.d(TAG, "Queuing the Periodic Work");
// Create a periodic request
final PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
.addTag(TAG_PERIODIC_WORK_REQUEST)
.build();
// Queue the work
workManager.enqueue(periodicWorkRequest);
else
Log.d(TAG, "Work Status Size: " + workStatuses.size());
for (int i = 0; i < workStatuses.size(); i++)
Log.d(TAG, "Work Status Id: " + workStatuses.get(i).getId());
Log.d(TAG, "Work Status State: " + workStatuses.get(i).getState());
Log.d(TAG, "Periodic Work already exists");
);
在上面的示例中,我使用了一个唯一标签 TAG_PERIODIC_WORK_REQUEST
来识别我的周期性工作,并在创建它之前检查它是否存在。
2) 当应用被终止时,您的工作可能没有运行。
您要测试的品牌是什么?是小米吗?您是否在其他多个品牌上进行过测试并得到相同的结果?
是否处于打盹模式?当您设置 24 小时时间时,您如何验证工作没有运行?
工作管理器提供向后兼容性,但您仍然需要处理设备特定的逻辑。在小米设备上,类似于 Job Scheduler(或 Firebase Job Dispatcher 或 Alarm),当应用被杀死时,周期性工作停止。
3) 我只是觉得WorkManager
提供的PeriodicWorkRequest
有问题。
自上周开始以来,我一直在多台设备上对其进行测试。我在第一次启动应用程序时创建了一个作品,并且三天没有打开它。第一次运行一次,触发第二次同步时运行两次,在这之间,它增加到 13 次,下降到 1 次,4 次等等。
在另一个测试中,我在第一次安装期间使用以下代码创建了一个作品,并从第二次安装中删除了该代码。在这个测试过程中,即使工作成功完成,工作每次都运行,杀死后打开应用程序。
final PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
.addTag("periodic-work-request")
.build();
// Queue the work
WorkManager.getInstance().enqueue(periodicWorkRequest);
我明白,因为它仍处于 alpha 阶段。我认为您不应该在生产中使用它。
【讨论】:
谢谢 Srikar。我使用的是小米设备,为了测试,我设置了 20 分钟。它运行不正确。希望我能再次回到作业调度程序。 在小米上,后台作业仅在将 省电模式 选项设置为 无 时运行。 不要认为JobScheduler
也会运行。如果有,请告诉我。
@SrikarReddy 小米设备有什么破解方法吗?
@AbhishekBatra 除了“自动启动”或“省电模式禁用”之外,你有没有针对红米手机的任何解决方案..【参考方案3】:
如果您在PeriodicWorkRequestBuilder
中添加标签,然后在将定期请求排入队列之前调用WorkManager.getInstance().cancelAllWorkByTag(REQUEST_TAG)
,这将防止欺骗发生:
Android Workmanager PeriodicWorkRequest is not unique
【讨论】:
【参考方案4】:从alpha03
开始,您可以安排一个独特的周期性工作:
https://developer.android.com/jetpack/docs/release-notes
WorkManager.enqueueUniquePeriodicWork(String uniqueWorkName, 现有的定期工作政策现有的定期工作政策, PeriodicWorkRequest periodWork) 允许您将唯一的 定期工作请求
所以现在实现你想要的就相当简单了。
【讨论】:
【参考方案5】:alpha 01 中存在以下问题:
修复了导致工人在 Application.onCreate() 上重新安排的问题。
使用最新版本的 WorkManager,即 1.0.0-alpha02。查看release notes了解更多信息
【讨论】:
我正在使用 1.0.0-alpha02 但仍然有同样的问题。 这里也一样。越来越多的工作创建每个应用程序启动。 看起来问题还没有解决【参考方案6】:使用 WorkManager 版本 1.0.0-alpha04。您可以查看发行说明here
此外,请参阅此PeriodicWorkRequest GitHub demo,它在维护时段内每天(每 24 小时)更新一次日计数器。它执行 doWork() 方法,无论应用程序是打开还是关闭。
WorkManager 仍处于 alpha 模式,因此一旦发布最终版本,它将完全适用于所有设备。
【讨论】:
以上是关于用于在后台运行日常任务的 Android WorkManager api的主要内容,如果未能解决你的问题,请参考以下文章
android现代化后台任务WorkManager,kotlin
RabbitMQ指南之二:工作队列(Work Queues)