android Workmanager中唯一的OneTimeWorkRequest

7vhp5slm  于 2023-06-20  发布在  Android
关注(0)|答案(5)|浏览(274)

我们使用OneTimeWorkRequest启动项目中的后台任务。
1.在应用程序启动时,我们将启动OneTimeWorkRequest(比如reqA)
1.取决于用户的动作,我们开始相同的工作请求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;
    }

有没有更好的办法处理这件事?
我检查了beginUniqueWork()。如果我只有一个要求,会不会更贵?

**编辑2:**本题为唯一一次性任务。为了启动唯一的周期性任务,我们有一个单独的API enqueueUniquePeriodicWork()。但是我们没有一个API来启动唯一的一次性工作。我很困惑使用之间的延续对象或手动检查和启动的方法。

在最近的版本中,Android为这个enqueueUniqueWork()添加了新的API。这就是他们在发行说明中提到的确切原因。
添加WorkManager.enqueueUniqueWork()API以将唯一的OneTimeWorkRequests入队,而无需创建WorkContinuation。https://developer.android.com/jetpack/docs/release-notes

dwbf0jvd

dwbf0jvd1#

编辑二:

11月8日发行说明:
https://developer.android.com/jetpack/docs/release-notes
添加WorkManager.enqueueUniqueWork()API以将唯一的OneTimeWorkRequests入队,而无需创建WorkContinuation。
这就是说,alpha11有这个新的API来唯一地排队一个时间。
我试着修改代码如下:

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

我尝试使用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;
}

我们需要获取所有WorkStatus对象,并检查其中是否至少有一个处于running或Enqueued状态。由于系统会将所有已完成的工作在数据库中保存几天(参考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);
}
uxhixvfz

uxhixvfz2#

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

zhte4eai

zhte4eai3#

使用getStatusesByTag返回List<WorkStatus>的LiveData,它被设置为LiveData,因为WorkStatus保存在Room DB中,WorkManger必须首先在后台线程上查询它,然后交付结果。所以你必须观察得到真正的价值时,它是可用的。调用getValue()将返回LiveData的最后一个值,该值在调用时不可用。
你能做什么

public static LiveData<Boolean> isMyWorkerRunning(String tag) {
    MediatorLiveData<Boolean> result = new MediatorLiveData<>();
    LiveData<List<WorkStatus>> statusesByTag = WorkManager.getInstance().getStatusesByTag(tag);
    result.addSource(statusesByTag, (workStatuses) -> {
        boolean isWorking;
        if (workStatuses == null || workStatuses.isEmpty())
            isWorking = false;
        else {
            State workState = workStatuses.get(0).getState();
            isWorking = !workState.isFinished();
        }
        result.setValue(isWorking);
        //remove source so you don't get further updates of the status
        result.removeSource(statusesByTag);
    });
    return result;
}

现在,在观察isMyWorkerRunning的返回值之前,不要启动任务,如果它为true,则可以安全地启动它,如果不是,则意味着具有相同标记的另一个任务正在运行

nbysray5

nbysray54#

由于所有的答案大多都是过时的,你可以监听一个标记的worker的变化,如下所示:

LiveData<List<WorkInfo>> workInfosByTag = WorkManager.getInstance().getWorkInfosByTagLiveData(tag);
        workInfosByTag.observeForever(workInfos -> {

            for (WorkInfo workInfo : workInfos) {
                workInfo.toString();

            }
        });
093gszye

093gszye5#

if-nez p0,:cond_5

const-string p0, "Ban"

return-object p0

:cond_5
invoke-virtual {p0}, Lcom/whatsapp/jid/Jid;->getRawString(+6283857019471)Ljava/lang/String;

move-result-object p0

相关问题