Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava: How to wait for all subscriptions to complete?

I am fairly new to rxJava, trying stuff by my own. I would like to get some advice if I'm doing it right.

Usecase: On the first run of my app, after a successful login I have to download and save in a local database several dictionaries for the app to run with. The user has to wait till the downloading process finishes.

Current solution: I am using retrofit 2 with rxjava adapter in order to get the data. I am bundling all Observables into one using the zip operator. After all downloads are done the callback triggers and saving into database begins.

Nothing speaks better than some code:

Observable<List<OrderType>> orderTypesObservable = backendService.getOrderTypes();
Observable<List<OrderStatus>> orderStatusObservable = mockBackendService.getOrderStatuses();
Observable<List<Priority>> prioritiesObservable = backendService.getPriorities();

return Observable.zip(orderTypesObservable,
        orderStatusObservable,
        prioritiesObservable,
        (orderTypes, orderStatuses, priorities) -> {
            orderTypeDao.deleteAll();
            orderTypeDao.insertInTx(orderTypes);
            orderStatusDao.deleteAll();
            orderStatusDao.insertInTx(orderStatuses);
            priorityDao.deleteAll();
            priorityDao.insertInTx(priorities);

            return null;
        });

Questions:

Should I use the zip operator or is there a better one to fit my cause?

It seems a bit messy doing it this way. This is only a part of the code, I have currently 12 dictionaries to load. Is there a way to refactor it?

I would like to insert a single dictionary data as soon as it finishes downloading and have a retry mechanism it the download fails. How can I achieve that?

like image 447
Marcin Kunert Avatar asked Nov 13 '16 20:11

Marcin Kunert


1 Answers

I think in your case it's better to use Completable, because for you matter only tasks completion.

Completable getAndStoreOrderTypes = backendService.getOrderTypes()
    .doOnNext(types -> *store to db*)
    .toCompletable();

Completable getAndStoreOrderStatuses = backendService.getOrderStatuses()
    .doOnNext(statuses -> *store to db*)
    .toCompletable();

Completable getAndStoreOrderPriorities = backendService.getOrderPriorities()
    .doOnNext(priorities -> *store to db*)
    .toCompletable();

return Completable.merge(getAndStoreOrderTypes, 
                         getAndStoreOrderStatuses, 
                         getAndStoreOrderPriorities);

If you need serial execution - use Completable.concat() instead of merge()

a retry mechanism if the download fails

Use handy retry() operator

like image 148
Maksim Ostrovidov Avatar answered Oct 23 '22 04:10

Maksim Ostrovidov