Skip to content

Instantly share code, notes, and snippets.

@jsaund
Last active July 13, 2017 00:08
Show Gist options
  • Save jsaund/e52b57e381148fbc6437553703dd2728 to your computer and use it in GitHub Desktop.
Save jsaund/e52b57e381148fbc6437553703dd2728 to your computer and use it in GitHub Desktop.
RxJava Android and Infinite Scrolling
public class RxEndlessScroller {
interface OnLoadMoreListener {
void loadMore();
}
private static class EndlessScrollListener extends RecyclerView.OnScrollListener {
private final int visibleItemCountThreshold;
@Nullable private OnLoadMoreListener loadMoreListener;
private int lastItemCount;
private int currentItemCount;
private int firstVisibleItemPosition;
private int visibleItemCount;
private boolean loading;
public EndlessScrollListener(int visibleItemCountThreshold) {
this.visibleItemCountThreshold = visibleItemCountThreshold;
reset();
}
public void setLoadMoreListener(@Nullable OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void reset() {
lastItemCount = 0;
currentItemCount = 0;
firstVisibleItemPosition = 0;
visibleItemCount = 0;
loading = true;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) {
final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
visibleItemCount = recyclerView.getChildCount();
currentItemCount = layoutManager.getItemCount();
firstVisibleItemPosition = getFirstVisibleItemPosition(layoutManager);
if (loading && currentItemCount > lastItemCount) {
loading = false;
lastItemCount = currentItemCount;
}
final int triggerPosition = firstVisibleItemPosition + visibleItemCountThreshold;
final boolean loadMore = triggerPosition >= (currentItemCount - visibleItemCount);
if (!loading && loadMore) {
Timber.d("End reached. Load more");
if (loadMoreListener != null) {
loadMoreListener.loadMore();
}
loading = true;
}
}
}
private int getFirstVisibleItemPosition(@NonNull RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof LinearLayoutManager) {
return ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
}
return 0;
}
}
@NonNull private final EndlessScrollListener endlessScrollListener;
public RxEndlessScroller(int visibleItemThreshold) {
endlessScrollListener = new EndlessScrollListener(visibleItemThreshold);
}
public Observable<Event> loadMore() {
return Observable.create(emitter -> {
final OnLoadMoreListener loadMoreListener = () -> emitter.onNext(Event.loadMore());
endlessScrollListener.setLoadMoreListener(loadMoreListener);
emitter.setCancellation(() -> endlessScrollListener.setLoadMoreListener(null));
}, Emitter.BackpressureMode.LATEST);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment