即使应用程序关闭,我也需要在后台每天调用一个API。我见过关于WorkManager API。对于我的方案,我尝试了定期工作请求,但不幸的是,它没有达到我的预期结果。我所做的是在应用程序类中使用此代码
PeriodicWorkRequest.Builder myWorkBuilder =
new PeriodicWorkRequest.Builder(MyWorker.class, 24,
TimeUnit.HOURS);
PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance().enqueue(myWork);
但是,当应用程序首次打开时,它会重复运行 11 次,而在 24 小时后它不会运行。拜托,任何人,帮我解决。
如果要确保不会多次创建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);
我认为有三个问题。
1( 每次enqueue
myWork
WorkManager
实例时,您都会创建新的定期工作。
试试吧,MyWorker.class
的doWork()
方法中的逻辑第一次运行一次,第二次运行两次。您很可能在工作管理器中添加了 11 个作品,这就是为什么它运行了 11 次,最后一次检查。如果您创建新作品并将其添加到工作管理器中,则myWork
运行次数会增加。
与作业计划程序类似,在将工作添加到工作管理器之前,必须检查工作是否存在。
示例代码:
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 小时时间时,您如何验证工作是否未运行?
工作管理器提供向后兼容性,但您仍然需要处理特定于设备的逻辑。在小米设备上,与作业调度程序(或 Firebase 作业调度程序或警报(类似,当应用被终止时,定期工作会停止。
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 阶段。我认为你不应该在生产中使用它。
如果向PeriodicWorkRequestBuilder
添加一个标签,然后在将定期请求排队之前调用WorkManager.getInstance().cancelAllWorkByTag(REQUEST_TAG)
,这将防止重复发生:
Android Workmanager PeriodicWorkRequest 不是唯一的
从alpha03
开始,您可以安排一个独特的定期工作: https://developer.android.com/jetpack/docs/release-notes
WorkManager.enqueueUniquePeriodicWork(String uniqueWorkName, 现有定期工作政策 现有定期工作政策, PeriodicWorkRequest periodicWork(允许您排队一个唯一的 定期工作请求
因此,实现您现在想要的东西非常简单。
alpha 01 中存在以下问题:
修复了导致在 Application.onCreate(( 上重新调度工作线程的问题。
使用最新版本的工作管理器,即 1.0.0-alpha02。查看发行说明以获取更多信息
使用 WorkManager 版本1.0.0-alpha04。您可以在此处查看发行说明
另外,请参阅此 PeriodicWorkRequest GitHub 演示,该演示在维护时段内每天(每 24 小时(更新一次日计数器。它执行 doWork(( 方法,无论应用程序是打开还是关闭。
WorkManager仍处于alpha模式,因此一旦发布最终版本,它将完全适用于所有设备。