Ziem
Ziem

Reputation: 6697

How to emit items from a list with delay in RxJava?

I'm using Retrofit to get bookmarks from REST API:

public interface BookmarkService {
    @GET("/bookmarks")
    Observable<List<Bookmark>> bookmarks();
}

Now I would like to emit each item from this list with delay.

I did something similar to this in Java, but onCompleted is never triggered.

private Observable<Bookmark> getBookmarks() {
    return getBookmarkService().bookmarks()
         .flatMap(new Func1<List<Bookmark>, Observable<Bookmark>>() {
            @Override
            public Observable<Bookmark> call(List<Bookmark> bookmarks) {
                Observable<Bookmark> resultObservable = Observable.never();
                for (int i = 0; i < bookmarks.size(); i++) {
                    List<Bookmark> chunk = bookmarks.subList(i, (i + 1));
                    resultObservable = resultObservable.mergeWith(Observable.from(chunk).delay(1000 * i, TimeUnit.MILLISECONDS));
                }

                return resultObservable;
            }
        })
        .observeOn(AndroidSchedulers.mainThread());
}

What I'm doing wrong?

Usage:

mSwipeRefreshLayout.setRefreshing(true);
getBookmarks()
    .subscribe(new Observer<Bookmark>() {
        @Override
        public void onCompleted() {
            Timber.i("Completed");
            mSwipeRefreshLayout.setRefreshing(false);
        }

        @Override
        public void onError(Throwable e) {
            Timber.i("Error: %s", e.toString());
            mSwipeRefreshLayout.setRefreshing(false);
        }

        @Override
        public void onNext(Bookmark bookmark) {
            Timber.i("Bookmark: %s", bookmark.toString());
            mBookmarksAdapter.addItem(bookmark);
        }
    });

Upvotes: 7

Views: 5467

Answers (1)

dwursteisen
dwursteisen

Reputation: 11515

As you use a merge operation, onCompleted will be call if all Observables are completed. but Observable.never() will never complete. Use Observable.empty() instead.

According to your code, your want to emit sublist with delay. The sublist contains only one element

What you can do : flatmap your list, to emit each items. Buffer it to build a list from items, then use a delay.

private Observable<Bookmark> getBookmarks() {
    return getBookmarkService().bookmarks()
                               .flatMap((bookmarks) -> Observable.from(bookmarks)
      .buffer(1)
      .scan(new Pair(0, null), (ac, value) -> new Pair(acu.index + 1, value)
      .flatMap(pair -> Observable.just(pair.value).delay(pair.index, SECONDS)) 
                               .observeOn(AndroidSchedulers.mainThread());
}

it might work (not tested)

Upvotes: 4

Related Questions