Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava - Chaining requests and updating UI

The problem I'm having is this. I need to execute couple of requests to the server. Each next request depends on the result of previous one. They look like this (abbreviated):

Observable<FileUploadResponse> obsFile = api.uploadFile();
Observable<TokenCreateResponse> obsCreateToken = api.createToken();
Observable<PaymentResponse> obsPayment = api.submitOrder();

I've created a single observable using a flatMap which returns the PaymentResponse object or emits onError() if some of the requirements aren't met. This is working fine and I get all the requests done in a single call.

The problem is I can't update the UI between these requests. With current setup, I show the loading when request starts and hide it when all the requests are complete. Is there a way to update the UI in-between these requests?

What I want is this: 1. File uploading - write a message on the UI. 2. Creating a token - write a message on the UI. 3. Submitting order - write a message on the UI. 4. Once all are complete, hide the progress dialog.

My understanding would be to emit some Observable using onNext() when each API call is finished and then calling onComplete() when all are done. But how do I do this?

like image 265
Tomislav Turcic Avatar asked Mar 07 '17 17:03

Tomislav Turcic


1 Answers

You could achieve this with doOnNext and a PublishSubject. First create a subject and some values:

public static final int STATUS_UPLOADING = 0;
public static final int STATUS_TOKEN = 1;
public static final int STATUS_SUBMITTING = 2;
public static final int STATUS_DONE = 3;

PublishSubject<Integer> status = PublishSubject.create();

public Observable<Integer> getStatusStream() {
    return status;
}

Then when you're doing your upload work just send the value to the subject each time:

status.onNext(STATUS_UPLOADING);

return api.uploadFile()
    .doOnNext(o -> status.onNext(STATUS_TOKEN))
    .flatMap(o -> api.createToken())
    .doOnNext(o -> status.onNext(STATUS_SUBMITTING))
    .flatMap(o -> api.submitOrder())
    .doOnNext(o -> status.onNext(STATUS_DONE))

Then you can subscribe to the Subject and update your UI:

model.getStatusStream()
    .subscribeOn(AndroidSchedulers.mainThread())
    .subscribe(
        status -> {
            view().setMessage(status);
        },
        Throwable.printStackTrace
    );

Alternatively depending on how you want to architect your app you could just call the update view calls from doOnNext each time. You'd probably need to use observeOn to switch between the main & background thread each time.

like image 117
Jahnold Avatar answered Oct 26 '22 20:10

Jahnold