Android Workmanager中唯一的OneTimeWorkRequest
我们正在使用OneTimeWorkRequest启动项目中的后台任务Android Workmanager中唯一的OneTimeWorkRequest,android,android-architecture-components,android-jetpack,android-workmanager,Android,Android Architecture Components,Android Jetpack,Android Workmanager,我们正在使用OneTimeWorkRequest启动项目中的后台任务 在应用程序启动时,我们正在启动OneTimeWorkRequest(比如req A) 根据用户的操作,我们启动相同的工作请求A 在某些情况下,如果应用程序在工作请求A进行时被终止,Android会在应用程序重新启动时自动重新启动请求A。我们也再次开始请求A。所以请求A的两个实例并行运行并导致死锁 为了避免这种情况,我在appstart中编写了下面的代码来检查worker是否正在运行,但这总是返回false public sta
public static boolean isMyWorkerRunning(String tag) {
List<WorkStatus> status = WorkManager.getInstance().getStatusesByTag(tag).getValue();
return status != null;
}
公共静态布尔isMyWorkerRunning(字符串标记){
列表状态=WorkManager.getInstance().GetStatuseByTag(tag).getValue();
返回状态!=null;
}
有没有更好的方法来处理这个问题
我检查了开始的工作()。如果我只有一个要求,成本会更高吗
编辑2:
这个问题是关于唯一的一次性任务。对于启动唯一定期任务,我们有一个单独的API enqueueUniquePeriodicWork()。但是,我们没有一个API来启动唯一的一次性工作。我对使用连续对象或手动检查和启动方法感到困惑
在最近的构建中,他们为这个enqueueUniqueWork()添加了新的api。这正是他们在发行说明中提到的原因
将WorkManager.enqueueUniqueWork()API添加到enqueue unique
OneTimeWorkRequests,而无需创建WorkContinuation。
您可以使用具有唯一名称的
beginUniqueWork()
。如果使用:
追加:这两个请求将连续运行。
保留:如果第一个请求正在运行,则不会运行第二个请求。
替换:这两个请求将并行运行。
使用
getStatusesByTag
返回列表的LiveData
之所以将其设置为LiveData,是因为WorkStatus保存在房间DB中,WorkManager必须首先在后台线程上查询它,然后交付结果。
因此,当它可用时,您必须观察以获得实际值。
调用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;
}
publicstaticlivedata isMyWorkerRunning(字符串标记){
MediatorLiveData结果=新的MediatorLiveData();
LiveData statusesByTag=WorkManager.getInstance().getStatusesByTag(标记);
结果.addSource(StatuseByTag,(工作状态)->{
布尔值正在工作;
if(workStatuses==null | | workStatuses.isEmpty())
isWorking=false;
否则{
State workState=workstatus.get(0.getState();
isWorking=!workState.isFinished();
}
结果。设定值(正在工作);
//删除源,这样您就不会获得状态的进一步更新
结果.removeSource(statusesByTag);
});
返回结果;
}
现在,在观察isMyWorkerRunning的返回值之前,您不会启动任务。如果该值为真,则可以安全地启动它。如果不是真的,则表示另一个具有相同标记的任务正在运行。编辑2:
11月8日发行说明:
将WorkManager.enqueueUniqueWork()API添加到enqueue unique
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);
我尝试使用BeginUniqueWorkAPI。但它有时无法运行。因此,我最终编写了以下函数
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;
}
由于所有答案大部分都已过时,因此您可以通过以下方式侦听已标记工作进程上的更改:
LiveData<List<WorkInfo>> workInfosByTag = WorkManager.getInstance().getWorkInfosByTagLiveData(tag);
workInfosByTag.observeForever(workInfos -> {
for (WorkInfo workInfo : workInfos) {
workInfo.toString();
}
});
LiveData workinfo-sbytag=WorkManager.getInstance().getworkinfo-sbytagiledata(标记);
WorkInfo-ByTag.ObserveForver(工作信息->{
用于(工作信息工作信息:工作信息){
workInfo.toString();
}
});
你为什么要运行任务,难道你不应该发射并忘记吗?不,一次性工作请求只是一次性发射。我们不定期运行此工作进程。我在应用程序重新启动期间运行此worker,因为应用程序不知道应用程序未运行的时间。此工作人员用于与电话簿内容同步。@Khemraj的可能重复项我的问题正是关于如何唯一地启动OneTimeWorkRequest()。这已包含在较新的版本中。请检查我的编辑。好的,这就是我的问题。如果调用beginUniqueWork(),它将返回continuation对象。如果我只有一个工作要求,那会更贵吗?我的意思是我没有一连串的工作要求。我们只有一个工作请求。您好,感谢更新,我对更新的代码没有什么混淆,如果我使用enqueueUniqueWork
,如果以前的工作已经在运行,它是否会添加一个新工作,即它是否检查workStatus.getState()==State.running
,就像您在代码中所做的那样。谢谢:)
LiveData<List<WorkInfo>> workInfosByTag = WorkManager.getInstance().getWorkInfosByTagLiveData(tag);
workInfosByTag.observeForever(workInfos -> {
for (WorkInfo workInfo : workInfos) {
workInfo.toString();
}
});