1

I have a question in order to understand better a RX Java solution with retrofit in Android, the problem is the following: I have an application that has an offline mode with a local database, while I'm working with the app, process in there are recorded into database and then send it to the backend to be saved. In this case I have some process that change status in a order, for example I have an action who change arriving status of a job, another who change a Job started status, and 4 more actions that change statuses in the a process. this statuses are saved into different local database tables and have to make multiple API call to change that statuses 1 for each status. explaning this, I have a screen in my app that group all process statuses for every JOB that are pending to send to backend, so in this case are grouped by ID of Job, so I would like to press a button in my app screen and send all of this statuses calling every API and get a result when finish with all that calls in order to put a loading progress and remove it when finish, clear local database with all statuses that where send it well, and finish activity. I know that RX Java has the ZIP option to call API's and wait for the result, but in this case I don't know if it's possible because I have to call every API for every same status of all jobs, example: I have JOB 1, 2, 3 and 4.

  1. Job 1 - Has status 1, status 2, status 3.
  2. Job 2 - Has status 1, status 2.
  3. job 3 - Has status 1, status 2, status 3, status 4.
  4. Job 4 - Has status 1.

Every status has 1 API to be cosumed. so I need to make a process who call every API gruped by status, call all API's and get response of every call in order to delete statuses for internal table and when all finish put ProgressBar = Hide and refresh a recycler view. I woul like to run all in parallel and get result when all calls finish. I don't know if i'm clear with my problem but if not, I coud explain it with more detail or answer your questions. Please I would happy with your help.

1 Answers1

2

Based on the answer posted here: How can I make this rxjava zip to run in parallel? I suggest zipping observables in parallel.

Suppose you build your calls to API like that:

public class Api {
    @POST("api 1 url")
    Observable<ResponseObject> postStatus1(...);

    @POST("api 2 url")
    Observable<ResponseObject> postStatus2(...);
}

You have to prepare your observables to be executed in parallel for selected job:

private Api api;

public List<Observable<ResponseObject>> prepareObservables(Job job) {
    List<Observable<ResponseObject>> list = new ArrayList<>();

    //Get all states for given job
    for(String status : job.getStates()) {
        // check which api method you need to call
        if(status.equals("STATUS1") {
            //subscribtion on a new thread will ensure calls are executed in parallel                
            list.add(api.postStatus1(...).subscribeOn(Schedulers.newThread()))
        }

        ...
    }

    return list;
}

Now zip the observables and execute

public void runObservables(List<Job> pendingJobs) {
    List<Observable<ResponseObject>> allObservables = new ArrayList<>();

    for(Job job : pendingJobs) {
        list.addAll(prepareObservables(job));
    }

    Observable.zip(allObservables, new Function<Object[], Object>() {
        @Override
        public Object apply(Object[] o) throws Exception {
            // you can combine respones from API here
        }).subscribe(new Consumer<Object>() {
            // this block of code executes when all calls to your api were successfull
            // do what you need to, i.e. delete jobs from db
        });
}
canihazurcode
  • 252
  • 2
  • 9
  • Hi Cani, I will try this now in order to check if works. I will tell you later. thanks – Martín De Girolamo Sep 13 '17 at 12:59
  • I have another question, you mark in there for selected JOB, and I need to send all jobs if there is more than one, so.... Do I need to make something else on that query ZIP to process all jobs, all statuses and get only 1 final evente? – Martín De Girolamo Sep 13 '17 at 13:45
  • Yes, I'll edit my answer. I'm not sure if I understand the way your API works. Do calls to your API accept lists of jobs, like `postStatus1(List jobs)` <- sends _all_ jobs which have status 1, or do you have to call `postStatus1(Job job)` _many_ times? – canihazurcode Sep 13 '17 at 14:32
  • Hi agian, unfortunately I have to call (Job job) Once pero job per status, It's really anoying but Backend people do not want to change API service. I will check if they want to change it in order to get a better resulto of it :(, even I will try to do something with your answer. – Martín De Girolamo Sep 13 '17 at 17:04
  • 1
    I edited my answer. Now it zips calls for every job on given list. – canihazurcode Sep 13 '17 at 19:29