43

如何检查是否WorkManager已安排。

这是我安排的代码WorkManager

public static void scheduleWork() {
    PeriodicWorkRequest.Builder photoCheckBuilder =
            new PeriodicWorkRequest.Builder(WorkManagerService.class, TIME_INTERVAL_IN_SECONDS,
                    TimeUnit.SECONDS);
    PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
    WorkManager instance = WorkManager.getInstance();
    if (instance != null) {
        instance.enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
    }
}

我打电话给scheduleWork()onCreate()Application班级。即使我可以通过这种方法检查我的服务是否正在运行。但是,如果 WorkManager 已经计划在计划的时间内消除不一致,我不想计划它。

喜欢

if(!workManagerIsScheduled())
   {
     scheduleWork();
   }

有什么解决办法吗?

4

6 回答 6

100

更新

如果您只是因为不想重复工作而需要检查已经运行的工作管理器。您可以简单地使用enqueueUniquePeriodicWork()

此方法允许您将唯一命名的 PeriodicWorkRequest 排入队列,其中一次只能激活一个特定名称的 PeriodicWorkRequest。例如,您可能只希望一个同步操作处于活动状态。如果有一个待处理,您可以选择让它运行或用您的新工作替换它。

所以你不必担心作品的重复。

 workmanager.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
  • 其中 TAG 是工作经理检查重复性的唯一名称。
  • 您可以在和之间进行选择ExistingPeriodicWorkPolicy.KEEPExistingPeriodicWorkPolicy.REPLACE

原帖

当我没有找到任何方法时,我创建了这个方法。

检查工作是否由 TAG 运行

if (your_work_manager.version >= 1.0.0-alpha11)

private boolean isWorkScheduled(String tag) {
    WorkManager instance = WorkManager.getInstance();
    ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(tag);
    try {
        boolean running = false;
        List<WorkInfo> workInfoList = statuses.get();
        for (WorkInfo workInfo : workInfoList) {
            WorkInfo.State state = workInfo.getState();
            running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
        }
        return running;
    } catch (ExecutionException e) {
        e.printStackTrace();
        return false;
    } catch (InterruptedException e) {
        e.printStackTrace();
        return false;
    }
}

if (your_work_manager.version < 1.0.0-alpha11)

private boolean isWorkScheduled(String tag) {
    WorkManager instance = WorkManager.getInstance();
    LiveData<List<WorkStatus>> statuses = instance.getStatusesByTag(tag);
    if (statuses.getValue() == null) return false;
    boolean running = false;
    for (WorkStatus workStatus : statuses.getValue()) {
        running = workStatus.getState() == State.RUNNING | workStatus.getState() == State.ENQUEUED;
    }
    return running;
}

true当它的一些任务是RUNNINGor时它会返回ENQUEUED

示例代码

public static final String TAG_MY_WORK = "mywork";

if(!isWorkScheduled(TAG_MY_WORK)) { // check if your work is not already scheduled
    scheduleWork(TAG_MY_WORK); // schedule your work
}

public static void scheduleWork(String tag) {
    PeriodicWorkRequest.Builder photoCheckBuilder =
            new PeriodicWorkRequest.Builder(WorkManagerService.class, TIME_INTERVAL_IN_SECONDS,
                    TimeUnit.SECONDS);
    PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
    WorkManager instance = WorkManager.getInstance();
    instance.enqueueUniquePeriodicWork(tag, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
}
于 2018-07-31T12:11:03.147 回答
6

1.0.0-alpha11以及许多WorkStatus将无法工作的东西被删除,这是一个重大变化。检查发行说明

WorkStatus 已重命名为 WorkInfo。所有相应的 getStatus 方法变体都已重命名为相应的 getWorkInfo 变体。这是一个突破性的变化。

更新到 alpha11 后,工作代码是。

private boolean isWorkScheduled(List<WorkInfo> workInfos) {

    boolean running = false;

    if (workInfos == null || workInfos.size() == 0) return false;

    for (WorkInfo workStatus : workInfos) {
        running = workStatus.getState() == WorkInfo.State.RUNNING | workStatus.getState() == WorkInfo.State.ENQUEUED;
    }

    return running;
}
于 2018-11-12T12:11:50.580 回答
3

自 2018 年 10 月 11 日起,您可以使用ListenableFuture而不是已删除的SynchronousWorkManager

您现在可以使用 ListenableFutures 同步获取和观察。例如,WorkManager.enqueue() 用于返回 void;它现在返回一个 ListenableFuture。操作完成后,您可以调用 ListenableFuture.addListener(Runnable, Executor) 或 ListenableFuture.get() 来运行代码。

更多信息可以在这里找到。

另一种选择是使用ListenableWorker

一个可以在 WorkManager 中异步执行工作的类。在大多数情况下,我们建议使用 Worker,它提供了一个简单的同步 API,在预先指定的后台线程上执行。

调用 startWork() 函数后,它会返回ListenableFuture 。

更多信息可以在这里找到。

于 2018-09-22T12:28:52.540 回答
3

接受的答案是错误的(很糟糕,因为它默默地失败了)。这里有一个正确答案

private boolean isWorkScheduled(String tag, Context context) {

        WorkManager instance = WorkManager.getInstance(context);
        ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(tag);

        boolean running = false;
        List<WorkInfo> workInfoList = Collections.emptyList(); // Singleton, no performance penalty

        try {
            workInfoList = statuses.get();
        } catch (ExecutionException e) {
            Log.d(TAG, "ExecutionException in isWorkScheduled: " + e);
        } catch (InterruptedException e) {
            Log.d(TAG, "InterruptedException in isWorkScheduled: " + e);
        }

        for (WorkInfo workInfo : workInfoList) {
            WorkInfo.State state = workInfo.getState();
            running = running || (state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED);
        }
        return running;

除了一些重构以避免误导多次返回之外,错误就在这一行

running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;

如果你使用这条线,你只会得到最后的评估running。有评论建议改用运算符=|。即使结果是正确的,代码也会不清楚并且(稍微)次优。 |是位运算符并且||是逻辑运算符。我们要执行的操作是逻辑的,而不是按位的。在布尔值上,|||给出相同的结果,但只是||快捷方式,这是我们案例中的预期行为。

此代码至少适用于 WorkManager 2.5.0 和 2.6.0。

于 2021-08-06T13:31:37.937 回答
2

我在这篇文章中找到了答案,并进行了一些编辑。

在我的项目中;我每 15 分钟向服务器发送一次位置信息。如果 WorkManager 已经安排好了,我不想安排它。

// Fırst I'm creating workRequest here.
   private void createWorkRequest() {
        Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
        PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder
                (LocationWorker.class, 15, TimeUnit.MINUTES)
                .setConstraints(constraints)
                .build();
        WorkManager.getInstance(this)
                .enqueueUniquePeriodicWork("sendLocation", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest);
    }

// Then i'm learning the state of Work
    private WorkInfo.State getStateOfWork() {
        try {
            if (WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation").get().size() > 0) {
                return WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation")
                        .get().get(0).getState();
                // this can return WorkInfo.State.ENQUEUED or WorkInfo.State.RUNNING
                // you can check all of them in WorkInfo class.
            } else {
                return WorkInfo.State.CANCELLED;
            }
        } catch (ExecutionException e) {
            e.printStackTrace();
            return WorkInfo.State.CANCELLED;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return WorkInfo.State.CANCELLED;
        }
    }

// If work not ( ENQUEUED and RUNNING ) i'm running the work.
// You can check with other ways. It's up to you.
    private void startServerWork() {
        if (getStateOfWork() != WorkInfo.State.ENQUEUED && getStateOfWork() != WorkInfo.State.RUNNING) {
            createWorkRequest();
            Log.wtf("startLocationUpdates", ": server started");
        } else {
            Log.wtf("startLocationUpdates", ": server already working");
        }
    }
于 2019-11-19T09:20:02.067 回答
1

我认为我们应该通过 UniqueWorkName 检查所有 WorkRequest 的六个状态。如果工作请求将处于任何状态,我们应该将其标记为已安排。您还可以删除案例中的一些状态以满足您的业务需求。

private fun isWorkEverScheduledBefore(context: Context, tag: String): Boolean {
    val instance = WorkManager.getInstance(context)
    val statuses: ListenableFuture<List<WorkInfo>> = instance.getWorkInfosForUniqueWork(tag)
    var workScheduled = false
    statuses.get()?.let {
        for (workStatus in it) {
            workScheduled = (
                        workStatus.state == WorkInfo.State.ENQUEUED
                                || workStatus.state == WorkInfo.State.RUNNING
                                || workStatus.state == WorkInfo.State.BLOCKED
                                || workStatus.state.isFinished // It checks SUCCEEDED, FAILED, CANCELLED already
                    )
        }
    }
    return workScheduled
}
于 2022-01-03T09:56:13.477 回答