Workmanager中的唯一OneTimeWorkRequest

Ara*_*ram 9 android android-architecture-components android-jetpack android-workmanager

我们正在使用OneTimeWorkRequest在我们的项目中启动后台任务.

  1. 在应用程序启动时,我们正在启动OneTimeWorkRequest(比如req A)
  2. 取决于用户的操作,我们开始相同的工作请求A.

在某些情况下,如果应用程序在工作请求A正在进行时被杀死,Android会在应用程序重新启动时自动重新启动请求A. 我们再次再次启动请求A. 因此,请求A的两个实例并行运行并导致死锁.

为了避免这种情况,我在app start中执行了以下代码来检查worker是否正在运行但是这总是返回false.

public static boolean isMyWorkerRunning(String tag) {
        List<WorkStatus> status = WorkManager.getInstance().getStatusesByTag(tag).getValue();
        return status != null;
    }
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来处理这个?

我检查了beginUniqueWork().如果我只有一个请求,是否更昂贵?

编辑2: 这个问题是关于独特的一次性任务.为了启动唯一的Periodic任务,我们有一个单独的API enqueueUniquePeriodicWork().但是我们没有用于启动独特的一次性工作的API.我很困惑在继续对象之间使用或手动检查和启动方法.

在最近的构建中,他们为这个enqueueUniqueWork()添加了新的api.这是他们在发行说明中提到的确切原因.

添加WorkManager.enqueueUniqueWork()API以将唯一的OneTimeWorkRequests排入队列,而无需创建WorkContinuation. https://developer.android.com/jetpack/docs/release-notes

Nic*_*ckF 7

您可以使用beginUniqueWork()唯一的名称。
如果您使用ExistingWorkPolicy :
APPEND: 2 个请求将串行运行。
KEEP:如果第一个请求正在运行,则不会运行第二个请求。
REPLACE:2 个请求将并行运行。


Ara*_*ram 6

编辑2:

11月8日发行说明:

https://developer.android.com/jetpack/docs/release-notes

添加WorkManager.enqueueUniqueWork()API以使唯一的OneTimeWorkRequest入队,而无需创建WorkContinuation。

这就是说,alpha11拥有这个新的API来唯一地排队一次工作。

我尝试如下更改代码:

OneTimeWorkRequest impWork = new OneTimeWorkRequest.Builder(WorkerNotesAttachment.class)
            .addTag(RWORK_TAG_NOTES)
            .build();
WorkManager.getInstance().enqueueUniqueWork(RWORK_TAG_NOTES, ExistingWorkPolicy.REPLACE, impWork);
Run Code Online (Sandbox Code Playgroud)

我尝试使用beginUniqueWork API。但是有时无法运行。因此,我最终编写了以下函数。

public static boolean isMyWorkerRunning(String tag) {
    List<WorkStatus> status = null;
    try {
        status = WorkManager.getInstance().getStatusesByTag(tag).get();
        boolean running = false;
        for (WorkStatus workStatus : status) {
            if (workStatus.getState() == State.RUNNING
                    || workStatus.getState() == State.ENQUEUED) {
                return true;
            }
        }
        return false;

    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

我们需要获取所有WorkStatus对象,并检查其中至少一个处于“运行”或“入队”状态。由于系统将所有已完成的工作保留在数据库中几天(请参阅pruneWork()),因此我们需要检查所有工作实例。

在启动OneTimeWorkRequest之前,请调用此函数。

public static void startCacheWorker() {

    String tag = RWORK_TAG_CACHE;

    if (isMyWorkerRunning(tag)) {
        log("worker", "RWORK: tag already scheduled, skipping " + tag);
        return;
    }
    // Import contact for given network
    OneTimeWorkRequest impWork = new OneTimeWorkRequest.Builder(WorkerCache.class)
            .addTag(tag)
            .build();
    WorkManager.getInstance().enqueue(impWork);
}
Run Code Online (Sandbox Code Playgroud)