将初始延迟设置为Android中的周期性工作管理器

时间:2018-08-21 09:18:41

标签: android kotlin android-workmanager

我有一个Worker实例,需要每24小时运行一次,考虑到PeriodicWorkRequest API而言,这非常简单。但这是要抓住的地方。

如果用户在晚上8点开始工作,我需要工作管理器的第一个实例在第二天早上9点运行,然后遵循24小时的周期性限制。

我看着here,发现OneTimeWorkRequest API具有可以使用的setInitialDelay()函数,但找不到PeriodicWork API的任何内容。

对此有一些技巧,例如我可以在初始延迟时使用OneTimeWork,然后从那里安排PeriodicWork,但这有点脏。

仅使用PeriodicWorkRequest API可以做到吗?

3 个答案:

答案 0 :(得分:3)

使用WorkManagerv1.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);