本文介绍了Workmanager中唯一的OneTimeWorkRequest的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We are using OneTimeWorkRequest to start background task in our project.

  1. 在应用程序启动时,我们正在启动OneTimeWorkRequest(例如req A)
  2. 根据用户的操作,我们启动相同的工作请求A.

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

At some cases, if the app gets killed when the work request A is in progress, Android automatically restarts the request A when the app restarts. Once again we are also starting the request A again. So two instances of the request A runs in parallel and leads to a deadlock.

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

To avoid this, I did below code in app start to check if the worker is running but this always returns false.

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

有没有更好的方法来解决这个问题?

Is there a better way to handle this?

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

I checked the beginUniqueWork(). Is it costlier if I have only one request?

修改2:这个问题是关于唯一的一次性任务.为了启动唯一的定期任务,我们有一个单独的API enqueueUniquePeriodicWork().但是,我们没有用于启动独特的一次性工作的API.我很困惑要在延续对象之间使用还是手动检查并启动方法.

Edit 2:This question is about unique One time task. For starting unique Periodic task we had a separate API enqueueUniquePeriodicWork(). But we did not have an API for starting unique onetime work. I was confused to use between continuation object or manually check and start approach.

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

In recent build they Android added new api for this enqueueUniqueWork(). This is the exact reason they mentioned in their release notes.

推荐答案

Edit 2:

11月8日发行说明:

Nov 8th release notes:

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

这表示,alpha11拥有这个新的API,可以唯一地排队一次工作.

This says, alpha11 has this new API to uniquely enqueue a onetimework.

我尝试如下更改代码:

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


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


I tried using the beginUniqueWork API. But it fails to run sometimes. So I ended up writing the following function.

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

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

We need to get all the WorkStatus objects and check if atleast one of them is in running or Enqueued state. As the system keeps all the completed works in the DB for few days (Refer pruneWork()), we need to check all the work instances.

在启动OneTimeWorkRequest之前调用此功能.

Invoke this function before starting the 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);
}

这篇关于Workmanager中唯一的OneTimeWorkRequest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 10:12