【问题标题】:Set initial delay to a Periodic Work Manager in Android在 Android 中为定期工作管理器设置初始延迟
【发布时间】:2019-01-27 10:49:07
【问题描述】:

我有一个 Worker 实例,它需要每 24 小时运行一次,考虑到 PeriodicWorkRequest API,这非常简单。但这就是问题所在。

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

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

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

有没有办法只使用PeriodicWorkRequest API 来做到这一点?

【问题讨论】:

    标签: android kotlin android-workmanager


    【解决方案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);
    

    【讨论】:

    • setInitialDelay 工作很奇怪。当我设置 15 分钟的启动时间和 1 分钟的初始延迟时,工作人员会在 16 分钟后启动。我认为它会立即(如OneTimeWorkRequest),但在 1 分钟后(而不是在 16 分钟后)。随后的启动将是每 15 分钟一次。
    • @proninyaroslav 定期工作的最小间隔为 15 分钟,并且不能有初始延迟。 MIN_PERIODIC_INTERVAL_MILLIS 为 15 分钟。 developer.android.com/reference/kotlin/androidx/work/…
    • 谢谢。我会尝试用OneTimeWorkRequest做一个技巧
    • PeriodicWorker 无法设置初始延迟,初始延迟仅适用于 oneTimeWorker
    • 我使用的是 implementation 'android.arch.work:work-runtime:1.0.1' 版本,而这里 setInitialDelay() 不存在。抱歉,我使用的是稳定版 WorkManager 而不是 alpha。
    【解决方案2】:

    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

    希望对你有帮助!

    【讨论】:

    • 文档说某些 API 版本(例如 23 版本)忽略了 flexTime...有没有合理的解决方案?
    【解决方案3】:

    WorkManager (v1.0.0-alpha07) 的当前 alpha 版本中,我认为无法为PeriodicWorkReqeust 设置初始延迟。也许我们会在下一个版本中获得一些 API。

    目前,正如您所说,您可以使用带有初始延迟的 OneTimeWork 请求设置,然后将 PeriodicWork 请求排队到 WorkManager。

    我会说这是一个 hack,但没那么脏。

    【讨论】:

    • 是的,这是我目前的策略。我只是想知道是否有任何直接的方法。
    • @qasim,有一些代码,如何实现?
    猜你喜欢
    • 2018-06-17
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 2020-05-10
    相关资源
    最近更新 更多