Проверьте, был ли WorkRequest ранее запущен WorkManager Android

Я использую PeriodicWorkRequest для выполнения задачи каждые 15 минут. Я хотел бы проверить, был ли ранее запланирован этот запрос на периодическую работу. Если нет, запланируйте это.

     if (!PreviouslyScheduled) {
        PeriodicWorkRequest dataupdate = new PeriodicWorkRequest.Builder( DataUpdateWorker.class , 15 , TimeUnit.MINUTES).build();
        WorkManager.getInstance().enqueue(dataupdate);
      }

Раньше, когда я выполнял задачу с помощью JobScheduler, я использовал

public static boolean isJobServiceScheduled(Context context, int JOB_ID ) {
    JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE ) ;

    boolean hasBeenScheduled = false ;

    for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
        if ( jobInfo.getId() == JOB_ID ) {
            hasBeenScheduled = true ;
            break ;
        }
    }

    return hasBeenScheduled ;
}

Нужна помощь в создании аналогичного модуля для запроса на работу, чтобы помочь найти запланированные / активные запросы на работу.


person Bhavita Lalwani    schedule 18.07.2018    source источник


Ответы (4)


Задайте тег для вашей задачи PeriodicWorkRequest:

    PeriodicWorkRequest work =
            new PeriodicWorkRequest.Builder(DataUpdateWorker.class, 15, TimeUnit.MINUTES)
                    .addTag(TAG)
                    .build();

Затем проверьте наличие задач с помощью TAG, прежде чем enqueue () сработает:

    WorkManager wm = WorkManager.getInstance();
    ListenableFuture<List<WorkStatus>> future = wm.getStatusesByTag(TAG);
    List<WorkStatus> list = future.get();
    // start only if no such tasks present
    if((list == null) || (list.size() == 0)){
        // shedule the task
        wm.enqueue(work);
    } else {
        // this periodic task has been previously scheduled
    }

Но если вам действительно не нужно знать, было ли это запланировано ранее или нет, вы можете использовать:

    static final String TASK_ID = "data_update"; // some unique string id for the task
    PeriodicWorkRequest work =
            new PeriodicWorkRequest.Builder(DataUpdateWorker.class,
                    15, TimeUnit.MINUTES)
                    .build();

    WorkManager.getInstance().enqueueUniquePeriodicWork(TASK_ID,
                ExistingPeriodicWorkPolicy.KEEP, work);

ExistingPeriodicWorkPolicy.KEEP означает, что задача будет запланирована только один раз, а затем будет периодически работать даже после перезагрузки устройства. В случае, если вам нужно перенастроить задачу (например, если вам нужно изменить некоторые параметры задачи), вам нужно будет использовать здесь ExistingPeriodicWorkPolicy.REPLACE

person Alex    schedule 30.10.2018

Вам нужно добавить уникальный тег к каждому WorkRequest. Проверьте Работа с тегами.

Вы можете логически сгруппировать свои задачи, назначив строку тега любому объекту WorkRequest. Для этого вам необходимо позвонить в WorkRequest.Builder.addTag().

Посмотрите ниже пример документа Android:

OneTimeWorkRequest cacheCleanupTask =
    new OneTimeWorkRequest.Builder(MyCacheCleanupWorker.class)
.setConstraints(myConstraints)
.addTag("cleanup")
.build();

То же, что вы можете использовать для PeriodicWorkRequest

Затем вы получите список всех рабочих состояний для всех задач с этим тегом, используя WorkManager.getStatusesByTag().

Что дает вам LiveData список _ 6_ для работы, помеченной тегом.

Затем вы можете проверить статус с помощью WorkStatus, как показано ниже:

       WorkStatus workStatus = listOfWorkStatuses.get(0);

        boolean finished = workStatus.getState().isFinished();
        if (!finished) {
            // Work InProgress
        } else {
            // Work Finished
        }

Вы можете проверить ниже пример Google для более подробной информации. Здесь добавили, как добавить тег в WorkRequest и получить статус работы по тегу:

https://github.com/googlecodelabs/android-workmanager

Изменения. Проверьте код ниже и прокомментируйте, как мы можем получить WorkStatus по тегу. И запланируйте нашу работу, если результаты WorkStatus пусты.

 // Check work status by TAG
    WorkManager.getInstance().getStatusesByTag("[TAG_STRING]").observe(this, listOfWorkStatuses -> {

        // Note that we will get single WorkStatus if any tag (here [TAG_STRING]) related Work exists

        // If there are no matching work statuses
        // then we make sure that periodic work request has been previously not scheduled
        if (listOfWorkStatuses == null || listOfWorkStatuses.isEmpty()) {
           // we can schedule our WorkRequest here
            PeriodicWorkRequest dataupdate = new PeriodicWorkRequest.Builder( DataUpdateWorker.class , 15 , TimeUnit.MINUTES)
                    .addTag("[TAG_STRING]")
                    .build();
            WorkManager.getInstance().enqueue(dataupdate);
            return;
        }

        WorkStatus workStatus = listOfWorkStatuses.get(0);
        boolean finished = workStatus.getState().isFinished();
        if (!finished) {
            // Work InProgress
        } else {
            // Work Finished
        }
    });

Я не тестировал код. Пожалуйста, поделитесь своим мнением о том же.

Надеюсь, это тебе поможет.

person pRaNaY    schedule 19.07.2018
comment
Спасибо, что ответили. Но AFAIK вы получите isFinished true, если состояние находится в состоянии Succeeded, Failed или Cancelled. Таким образом, это может дать ошибочные результаты, например, когда рабочий запрос был отменен и больше не запланировано, он даст истину и скажет, когда задача не добавлена, он даст ложь. Нам нужен какой-то подход, где мы можем узнать, запланирована ли задача / поставлена ​​ли она в очередь. - person Bhavita Lalwani; 19.07.2018

Я тоже искал такое же условие, но не нашел, поэтому для решения этой проблемы я нашел механизм: сначала отмените все запланированные работы и снова перенесите их. Так что мы можем гарантировать, что будет поддерживаться только один экземпляр вашей работы. Также убедитесь, что вы должны поддерживать такую ​​логику рабочего кода.

За отмену работы. Для получения дополнительных сведений

UUID compressionWorkId = compressionWork.getId();
WorkManager.getInstance().cancelWorkById(compressionWorkId);
person AtHul Antony    schedule 19.07.2018
comment
Вместо отмены работы вы можете добавить тег в запрос и проверить статус по тегу. Мой ответ может вам помочь. - person pRaNaY; 19.07.2018
comment
Хорошо. Но разработчику нужно превратить свою текущую работу в отложенное событие, если предыдущая работа не завершена, верно? Я не думаю, что нет другого механизма, чтобы добавить дополнительную работу к текущей работе. У меня также была ситуация с такой логикой, и я решил ее, отменив и изменив расписание. @pRaNaY - person AtHul Antony; 19.07.2018
comment
Спасибо за ответ и подход. Но я не думаю, что хочу каждый раз отменять свою задачу и переносить ее, это как-то нарушит периодическое свойство. Я просто хочу знать, запланировано ли какое-то задание или нет. - person Bhavita Lalwani; 19.07.2018
comment
Хорошо @BhavitaLalwani - person AtHul Antony; 19.07.2018
comment
@AtHulAntony Пожалуйста, проверьте мой обновленный ответ. Может тебе поможет. - person pRaNaY; 19.07.2018

сохраните тот же идентификатор задачи с ExistingPeriodicWorkPolicy.KEEP не будет создавать новую задачу каждый раз.

.enqueueUniquePeriodicWork (TASK_ID, ExistingPeriodicWorkPolicy.KEEP, работа);

person Ashish Chaugule    schedule 22.07.2020