Which operator or transform should I be using to combine two data streams in smallest amount of code and in the most efficient way?
With an Android ViewPager, I'm observing events (using RxBinding)
1) OnPageSelected (page currently visible)
Observable<Integer> pageSelectObs = RxViewPager.pageSelections(mPlaceImageViewPager);
and
2) OnPageScrollStateChanged (swipe starting = 1, in motion = 2, complete = 0)
Observable<Integer> scrollStateObs = RxViewPager.pageScrollStateChanges(mPlaceImageViewPager);
The stream of Integers looks like this:
I/System.out: Page: 0 ScrollState: 1
I/System.out: Page: 0 ScrollState: 2
I/System.out: Page: 1 ScrollState: 2
I/System.out: Page: 1 ScrollState: 0
I/System.out: Page: 1 ScrollState: 1
I/System.out: Page: 1 ScrollState: 2
I/System.out: Page: 2 ScrollState: 2
I/System.out: Page: 2 ScrollState: 0
I'm only interested when:
This is how I'm currently observing:
Disposable d = ObservableCombineLatest.combineLatest(pageSelectObs, scrollStateObs, new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(@NonNull Integer pageSelected, @NonNull Integer scrollState) throws Exception {
AUtils.logSystem(TAG, "Page: %s ScrollState: %s", pageSelected, scrollState);
if (adapter.isLastVisibleItem(pageSelected) && adapter.hasHiddenItemsRight() && scrollState == 0) {
return 1;
}
if (adapter.isFirstVisibleItem(pageSelected) && adapter.hasHiddenItemsLeft() && scrollState == 0) {
return -1;
}
return 0;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer doAction) throws Exception {
if (doAction == -1) {
AUtils.logSystem(TAG, "shift LEFT");
adapter.shiftLeft();
}
if (doAction == 1) {
AUtils.logSystem(TAG, "shift RIGHT");
adapter.shiftRight();
}
}
});
Is there a simpler way of doing the above?
Since your conditions are quite simple, you can express them with a simple filter()
operator.
Observable<Integer> scrollStateObs = RxViewPager.pageScrollStateChanges(mPlaceImageViewPager)
.filter(scrollState -> scrollState == ViewPager.SCROLL_STATE_IDLE);
In order to only react on scrollState
changes, you can use withLatestFrom()
operator
Disposable d = pageSelectObs.withLatestFrom(scrollStateObs, (pageSelected, scrollState) -> pageSelected)
.filter(pageSelected -> adapter.isLastVisibleItem(pageSelected));
.subscribe(pageSelected -> {
if (adapter.hasHiddenItemsRight()) {
adapter.shiftRight();
} else if (adapter.hasHiddenItemsLeft()) {
adapter.shiftRight();
}
});