Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Workmanager中唯一的OneTimeWorkRequest_Android_Android Architecture Components_Android Jetpack_Android Workmanager - Fatal编程技术网

Android Workmanager中唯一的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

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

  • 在应用程序启动时,我们正在启动OneTimeWorkRequest(比如req A)
  • 根据用户的操作,我们启动相同的工作请求A
  • 在某些情况下,如果应用程序在工作请求A进行时被终止,Android会在应用程序重新启动时自动重新启动请求A。我们也再次开始请求A。所以请求A的两个实例并行运行并导致死锁

    为了避免这种情况,我在appstart中编写了下面的代码来检查worker是否正在运行,但这总是返回false

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