Android WorkManager返回多个结果

3
我对WorkManager(以及Java)还比较新,似乎遇到了一些问题。 基本上,我们有一个应用程序,用户可以将一些记录上传到服务器。
上传它们不是问题。然而,我们希望在网络断开连接的情况下能够继续上传。经过一些研究,我偶然发现了WorkManager。观看了多个视频和几个教程后,我们决定试一试。
我让它工作了(有点),但出现了一个问题,它返回了多个结果,而不仅仅是一个。 我想要做的是,在所有记录都更新后,只返回一次结果(成功或失败),然后使用AlertDialog显示是否成功。 我认为它为工作请求中的每个数据项返回了一个结果,而不仅仅是一次。 但我不确定为什么,也不知道该如何解决。 当我运行它3次时,会出现3个AlertDialogs,前两个不会显示正确的信息,但最后一个会。
具体来说: 当单击上传按钮时,我调用一个UpLoadBatchRecords方法。 UploadBatchRecords方法设置数据、约束并排队工作请求:
public void UploadBatchRecords() {
        BatchMaster batchMaster = batchList.get(curBatchPosition);
        final Data data = new Data.Builder()
                .putInt(String.valueOf(NetworkConnected.CUR_POSITION), curBatchPosition)
                .putString(NetworkConnected.currentModule, batchMaster.ModuleName)
                .putString(NetworkConnected.currentBatch, batchMaster.BatchID)
                .build();

        Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();


        final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(NetworkConnected.class)
                .setInputData(data)
                .setConstraints(constraints)
                .build();

        WorkManager.getInstance().enqueue(workRequest);

        WorkManager.getInstance().getWorkInfoByIdLiveData(workRequest.getId())
                   .observe(this, new Observer<WorkInfo>() {
                               @Override
                               public void onChanged(WorkInfo workInfo) {
                                   if (workInfo.getState().isFinished() && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                                       message = workInfo.getOutputData().getString(NetworkConnected.KEY_SUCCESS);
                                   }
                                   else {
                                       message = workInfo.getOutputData().getString(NetworkConnected.KEY_FAILURE);
                                   }

                                   alert(message);
                               }
                           });
    }

工作者类:

public class NetworkConnected extends Worker {
    public NetworkConnected(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    private ArrayList<BatchMaster> batchList;
    public static final int CUR_POSITION = 0;
    public static final String currentModule = "Module Name";
    public static final String currentBatch = "Batch ID";
    public static final String KEY_SUCCESS = "Success";
    public static final String KEY_FAILURE = "Failure";

        @NonNull
    @Override
    public Result doWork() {
            int curPosition = getInputData().getInt(String.valueOf(CUR_POSITION), 0);
            String moduleName = getInputData().getString(currentModule);
            String batchID = getInputData().getString(currentBatch);
            LoadBatches();

            try {

                UploadBatchRecords(curPosition, moduleName, batchID);

                Data success = new Data.Builder()
                        .putString(KEY_SUCCESS, " records have been updated \n\n")
                        .build();

                return Result.success(success);
            }
            catch (Exception e) {
                Data failure = new Data.Builder()
                        .putString(KEY_FAILURE, " records failed to upload")
                        .build();
                return Result.failure(failure);
            }
        }

    public void UploadBatchRecords(Integer curPosition, String modName, String batchID) {
        int seqNum;
        String recordData;

        Cursor cur = Global.dbManager.fetchBatchRecords(companyID, modName, batchID);
        while (cur.moveToNext()) {
            seqNum = cur.getInt(cur.getColumnIndex("SequenceNumber"));
            recordData = cur.getString(cur.getColumnIndex("RecordData"));

            BatchRecordWebService(curPosition, seqNum, recordData);
        }
        cur.close();
    }

    public void BatchRecordWebService(Integer position, Integer seqNum, String recordData) {
        BatchMaster batchMaster = batchList.get(position);

        final WebService webservice = new WebService();

        webservice.setMethodName("UploadRecord");
        ArrayList<PropertyInfo> props = new ArrayList<>();
        AddWebServiceProperty(props, "CompanyID", companyID, String.class);
        AddWebServiceProperty(props, "ModuleName", batchMaster.ModuleName, String.class);
        AddWebServiceProperty(props, "BatchID", batchMaster.BatchID, String.class);
        AddWebServiceProperty(props, "SequenceNumber", seqNum.toString(), String.class);
        AddWebServiceProperty(props, "RecordData", recordData, String.class);
        AddWebServiceProperty(props, "CreatedBy", batchMaster.CreatedBy, String.class);
        AddWebServiceProperty(props, "CreatedDate", batchMaster.CreatedDate, String.class);
        AddWebServiceProperty(props, "UploadedBy", batchMaster.UpdatedBy, String.class);
        AddWebServiceProperty(props, "UploadDate", batchMaster.UpdatedDate, String.class);

        webservice.setSoapProperties(props);

        try {
            webservice.execute().get();

            if (webservice.getSuccess()) {
                Global.count++;
            }
            else{
                Global.failedCount++;
            }
        } catch (Exception ignored) {
        }
    }

    public void LoadBatches() {
        batchList = new ArrayList<>();

        Cursor cur = Global.dbManager.fetchBatches();
        while (cur.moveToNext()) {
            BatchMaster view = new BatchMaster(cur.getString(cur.getColumnIndex("ModuleName")),
                    cur.getString(cur.getColumnIndex("BatchID")),
                    cur.getString(cur.getColumnIndex("FormatName")),
                    cur.getInt(cur.getColumnIndex("RecordCount")),
                    cur.getString(cur.getColumnIndex("CreatedBy")),
                    cur.getString(cur.getColumnIndex("CreateDate")),
                    cur.getString(cur.getColumnIndex("UpdatedBy")),
                    cur.getString(cur.getColumnIndex("UpdateDate")));
            batchList.add(view);
        }
        cur.close();
   }

我不确定自己缺少什么,但我相信这是一些愚蠢的事情。如果你能提供任何帮助,那将非常感谢!谢谢!

2个回答

3

在返回多个结果而不是一个结果时,这是预期的。

这是因为onChanged()方法会在状态改变时被调用,无论工作是否完成。

    /**
     * Returns {@code true} if this State is considered finished.
     *
     * @return {@code true} for {@link #SUCCEEDED}, {@link #FAILED}, and * {@link #CANCELLED}
     *         states
     */
    public boolean isFinished() {
        return (this == SUCCEEDED || this == FAILED || this == CANCELLED);
    }

当你的任务处于任何一个(SUCCEEDED | FAILED | CANCELLED)状态时, WorkInfo isFinished()被调用。

但是还有其他状态,如ENQUEUED | RUNNING | BLOCKED。

所以,onChanged()方法会在任何这些状态下被调用,

我想做的就是在所有记录都更新完成之后只返回一次结果(成功或失败),然后使用AlertDialog来显示是否成功。

但由于需要在整个工作返回结果后才需要此功能,则需要将代码包装在if (workInfo.getState().isFinished())中,但对于else分支中的所有其他状态都被否定。

要实现这个:

WorkManager.getInstance().getWorkInfoByIdLiveData(workRequest.getId())
           .observe(this, new Observer<WorkInfo>() {
                       @Override
                       public void onChanged(WorkInfo workInfo) {
                           if (workInfo.getState().isFinished() {
                               if (workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                                   message = workInfo.getOutputData().getString(NetworkConnected.KEY_SUCCESS);
                               }
                               else {
                                   message = workInfo.getOutputData().getString(NetworkConnected.KEY_FAILURE);
                               }

                               alert(message);
                           }
                       }
                   });

太棒了!谢谢!我还想知道,如果约束条件失败(即网络未连接),状态是否保持在排队中?我也了解到它只会“保留”工作15分钟,之后会自动取消?我可能错了。本质上,我正在尝试找出一种方法,在约束条件失败时发送通知,据我所知,使用排队状态是实现这一目标的最佳方式。 - Patrick Davis
是的,它仍然在排队中,但当网络可用时,您也可以替换整个工作以从头开始。您还可以指数级增加退避时间,以便尽可能多地重试工作。但这需要您返回WorkerResult.RETRY请查看此文章 - Zain

0

好吧,这是一些愚蠢的东西。 已更改

else {
  message = workInfo.getOutputData().getString(NetworkConnected.KEY_FAILURE);
                                       alert(message);
                                   }

                               }
                           });

到:

else if (workInfo.getState() == WorkInfo.State.FAILED) {
                                       message = workInfo.getOutputData().getString(NetworkConnected.KEY_FAILURE);
                                       alert(message);
                                   }

                               }
                           });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接