Created
April 26, 2018 11:06
-
-
Save saber-solooki/0db2f49c88657e3f61b9f892d43410ee to your computer and use it in GitHub Desktop.
Detect when the RecyclerView reaches the bottom in Observable manner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.saber.ekip.views.rxRecyclerView; | |
import android.support.annotation.CheckResult; | |
import android.support.annotation.NonNull; | |
import android.support.v7.widget.RecyclerView; | |
import io.reactivex.Observable; | |
import static com.saber.ekip.views.rxRecyclerView.Preconditions.checkNotNull; | |
/** | |
* Created by sabersolooki on 1/5/18. | |
*/ | |
public class MyRxRecyclerView { | |
@CheckResult | |
@NonNull | |
public static Observable<Integer> pagingChanges(@NonNull RecyclerView view) { | |
checkNotNull(view, "view == null"); | |
return new RecyclerViewPagingObservable(view); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.saber.ekip.views.rxRecyclerView; | |
import android.support.v7.widget.LinearLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.util.Log; | |
import com.google.android.flexbox.FlexboxLayoutManager; | |
import java.util.HashMap; | |
import java.util.Map; | |
import io.reactivex.Observable; | |
import io.reactivex.Observer; | |
import io.reactivex.android.MainThreadDisposable; | |
import static com.saber.ekip.views.rxRecyclerView.Preconditions.checkMainThread; | |
/** | |
* Created by sabersolooki on 1/5/18. | |
*/ | |
final public class RecyclerViewPagingObservable extends Observable<Integer>{ | |
private final RecyclerView view; | |
RecyclerViewPagingObservable(RecyclerView view) { | |
this.view = view; | |
} | |
@Override | |
protected void subscribeActual(Observer<? super Integer> observer) { | |
if (!checkMainThread(observer)) { | |
return; | |
} | |
Listener listener = new Listener(view, observer); | |
observer.onSubscribe(listener); | |
view.addOnScrollListener(listener.scrollListener); | |
if (view.getAdapter() != null) { | |
view.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { | |
@Override | |
public void onChanged() { | |
super.onChanged(); | |
listener.calculatedPage.clear(); | |
listener.counter = 1; | |
} | |
}); | |
} | |
} | |
final class Listener extends MainThreadDisposable { | |
private final RecyclerView recyclerView; | |
private final RecyclerView.OnScrollListener scrollListener; | |
private int pastVisibleItems, visibleItemCount, totalItemCount; | |
private int counter = 1; | |
private Map<Integer, Integer> calculatedPage = new HashMap<>(); | |
Listener(RecyclerView recyclerView, final Observer<? super Integer> observer) { | |
this.recyclerView = recyclerView; | |
final RecyclerView.LayoutManager layoutManager = this.recyclerView.getLayoutManager(); | |
this.scrollListener = new RecyclerView.OnScrollListener() { | |
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { | |
try { | |
visibleItemCount = layoutManager.getChildCount(); | |
totalItemCount = layoutManager.getItemCount(); | |
if (layoutManager instanceof LinearLayoutManager) | |
pastVisibleItems = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); | |
else if (layoutManager instanceof FlexboxLayoutManager) | |
pastVisibleItems = ((FlexboxLayoutManager) layoutManager).findFirstVisibleItemPosition(); | |
else | |
Log.w("RxRecyclerView", "Your layout manager is not appropriate for paging."); | |
} | |
catch (NullPointerException e) { | |
throw new NullPointerException("Layout manager is null.You should set manager before set observable"); | |
} | |
if (!calculatedPage.containsKey(totalItemCount)) { | |
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) { | |
calculatedPage.put(totalItemCount, counter); | |
counter++; | |
if (!isDisposed()) { | |
observer.onNext(counter); | |
} | |
} | |
} | |
} | |
}; | |
} | |
@Override protected void onDispose() { | |
recyclerView.removeOnScrollListener(scrollListener); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment