Check if WorkRequest has been previously enquequed

2020-07-02 11:10发布

I am using PeriodicWorkRequest to perform a task for me every 15 minutes. I would like to check, if this periodic work request has been previously scheduled. If not, schedule it.

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

Previously when I was performing task using JobScheduler, I used to use

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 ;
}

Need help constructing a similar module for work request to help find scheduled/active workrequests.

3条回答
Lonely孤独者°
2楼-- · 2020-07-02 11:38

Set some Tag to your PeriodicWorkRequest task:

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

Then check for tasks with the TAG before enqueue() work:

    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
    }

But if you dont really need to know that it was previously scheduled or not, you could use:

    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 means that the task will be scheduled only once and then work periodically even after device reboot. In case you need to re-schedule the task (for example in case you need to change some parameters of the task), you will need to use ExistingPeriodicWorkPolicy.REPLACE here

查看更多
闹够了就滚
3楼-- · 2020-07-02 11:39

I was also searching for the same condition.I couldn't find one.So in order to solve this problem i found a mechanism.First cancel all scheduled works and reschedule the work again. So that we can ensure that only one instance of your work will be maintained. Also please be ensure that you have to maintain your worker code logic like that.

For canceling a work. For more

UUID compressionWorkId = compressionWork.getId();
WorkManager.getInstance().cancelWorkById(compressionWorkId);
查看更多
Evening l夕情丶
4楼-- · 2020-07-02 11:56

You need to add a unique tag to every WorkRequest. Check Tagged work.

You can group your tasks logically by assigning a tag string to any WorkRequest object. For that you need to call WorkRequest.Builder.addTag()

Check below Android doc example:

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

Same you can use for PeriodicWorkRequest

Then, You will get a list of all the WorkStatus for all tasks with that tag using WorkManager.getStatusesByTag().

Which gives you a LiveData list of WorkStatus for work tagged with a tag.

Then you can check status using WorkStatus as below:

       WorkStatus workStatus = listOfWorkStatuses.get(0);

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

You can check below google example for more details. Here they added how to add a tag to WorkRequest and get status of work by tag :

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

Edits Check below code and comment to how we can get WorkStatus by tag. And schedule our Work if WorkStatus results empty.

 // 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
        }
    });

I have not tested code. Please provide your feedback for the same.

Hope this helps you.

查看更多
登录 后发表回答