我有一个Worker
实例,需要每24小时运行一次,考虑到PeriodicWorkRequest
API而言,这非常简单。但这是要抓住的地方。
如果用户在晚上8点开始工作,我需要工作管理器的第一个实例在第二天早上9点运行,然后遵循24小时的周期性限制。
我看着here,发现OneTimeWorkRequest API具有可以使用的setInitialDelay()
函数,但找不到PeriodicWork
API的任何内容。
对此有一些技巧,例如我可以在初始延迟时使用OneTimeWork
,然后从那里安排PeriodicWork
,但这有点脏。
仅使用PeriodicWorkRequest
API可以做到吗?
答案 0 :(得分:3)
使用WorkManager
(v1.0.0-alpha07
)的当前Alpha版本,我认为无法为PeriodicWorkReqeust
设置初始延迟。也许我们会在下一个版本中获得一些API。
如您所说,暂时可以使用具有初始延迟的OneTimeWork
请求设置,然后将PeriodicWork
请求排队到WorkManager。
我会说这是一个hack,但是没有那么脏。
答案 1 :(得分:1)
PeriodicWorkRequest 有一个不错的Builder构造函数,您可以在其中传递可以执行工作的时间间隔。您可以检查Builder的详细信息以及每个参数here
因此,要为您的定期工作设置初始延迟,您可以这样做:
int hourOfTheDay = 10; // When to run the job
int repeatInterval = 1; // In days
long flexTime = calculateFlex(hourOfTheDay, repeatInterval);
Constraints myConstraints = new Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build();
PeriodicWorkRequest workRequest =
new PeriodicWorkRequest.Builder(MyNiceWorker.class,
repeatInterval, TimeUnit.DAYS,
flexTime, TimeUnit.MILLISECONDS)
.setConstraints(myConstraints)
.build();
WorkManager.getInstance().enqueueUniquePeriodicWork(YOUR_NICE_WORK_TAG,
ExistingPeriodicWorkPolicy.REPLACE,
workRequest);
神奇的地方在这里:
private long calculateFlex(int hourOfTheDay, int periodInDays) {
// Initialize the calendar with today and the preferred time to run the job.
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, hourOfTheDay);
cal1.set(Calendar.MINUTE, 0);
cal1.set(Calendar.SECOND, 0);
// Initialize a calendar with now.
Calendar cal2 = Calendar.getInstance();
if (cal2.getTimeInMillis() < cal1.getTimeInMillis()) {
// Add the worker periodicity.
cal2.setTimeInMillis(cal2.getTimeInMillis() + TimeUnit.DAYS.toMillis(periodInDays));
}
long delta = (cal2.getTimeInMillis() - cal1.getTimeInMillis());
return ((delta > PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS) ? delta
: PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS);
}
请注意,这次不正确。 WorkManager 可能随时在弹性窗口中触发您的作业,具体取决于您的约束,系统负载,其他计划的作业等。
如果需要精确的时间,请切换到 AlarmManager 。
希望有帮助!
答案 2 :(得分:1)
在新版本的工作管理器(Version 2.1.0-alpha02,2019年5月16日发布)上,PeriodicWorkRequests现在支持初始延迟。您可以在PeriodicWorkRequest.Builder上使用setInitialDelay方法来设置初始延迟。
示例:
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
WorkerReminderPeriodic.class,
24,
TimeUnit.HOURS,
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
TimeUnit.MILLISECONDS)
.setInitialDelay(1, TimeUnit.HOURS)
.addTag("send_reminder_periodic")
.build();
WorkManager.getInstance()
.enqueueUniquePeriodicWork("send_reminder_periodic", ExistingPeriodicWorkPolicy.REPLACE, workRequest);