'Check for work items from w/in a class for usage in a "batch" process and viewable in a settings screen - challenged w/LiveData or ListenableFuture

I'm probably making this harder than it is, but I want to encapsulate logic within a class so I can call it from two places and it is consistent. I want to check to see if:

  • All enqueued work is completed
  • If there are any un-synced records

If both of these things are true I want to:

  • Pull the next 10 records and enqueue them

I guess I am trying to avoid a bunch of things being enqueued at once in case we get behind. On starting up the app, I will run this check, and from the Settings fragment the work will be listed/viewable (so I have a way to understand what is happening in case of trouble...like can delete a work item). Here are two methods in the helper class.

public static WorkQuery getWorkQuery() {
    //check to see if the workerManager is free or busy
    return WorkQuery.Builder
            .fromTags(Arrays.asList("scenarioRun"))
            .addStates(Arrays.asList(
                    WorkInfo.State.FAILED,
                    WorkInfo.State.ENQUEUED,
                    WorkInfo.State.RUNNING,
                    WorkInfo.State.BLOCKED))
            .build();
}


public void enqueueNextBatch() {

    Log.d(TAG, "enqueueNextBatch: ");
    //here is where I would like to see if there is any unfinished work in the queue

    ScenarioRunRepository repository = new ScenarioRunRepository(context);

    Log.d(TAG, "enqueueNextBatch: getting scenarioList");
    List<ScenarioRun> scenarioList = repository.getNextSyncBatch();


    CloudSync cloudSync = new CloudSync.Builder()
            .setContext(context)
            .build();

    for (ScenarioRun scenarioRun: scenarioList) {
        Log.d(TAG, "enqueueNextBatch: " + scenarioRun.displayName());
        // I have the code to enqueue a scenarioRun
    }
}

When I am in the settings fragment I use this:

    viewModel.setWorkInfoList(WorkManager.getInstance(getContext()).getWorkInfosLiveData(SyncManager.getWorkQuery()));
    viewModel.getWorkInfoList().observe(getViewLifecycleOwner(), workInfoObserver);

and have an observer:

final Observer<List<WorkInfo>> workInfoObserver = new Observer<List<WorkInfo>>() {
    @Override
    public void onChanged(List<WorkInfo> workInfos) {
        workerAdapter.setWorkers(workInfos);
    }
};

I wanted to batch the work in the class, so my code to call this on startup would be:

            Executors.newSingleThreadExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "run: ");
                    SyncManager syncManager = new SyncManager(getContext());
                    syncManager.enqueueNextBatch();
                }
            });

I don't know if it's better to try to make this work with ListenableFuture of LiveData...or if I am approaching this completely wrong. Do I have the Observer/ListenableFuture in the class? Does anybody some sample code to help?

I always seem to struggle w/having a batch process (unattended) which shares logic with an interactive process. Obviously I'm not an expert programmer, but even the enqueueing a worker forced me to "de-callbackify" my process. Probably an area I need to invest more time in understanding, but hopefully a response here will help.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source