rxbinding-recyclerview-v7とPublishSubjectを使ってRecyclerViewでスクロールが一番下まで行ったらロードする実装
すでにある気がするけど見当たらなかったのでメモ。
ソース
こちらにあります。
GitHub - sys1yagi/rxrecyclerview-load-more
準備
rxbinding-recyclerview-v7をdependenciesに追加する。
dependencies {
compile 'com.jakewharton.rxbinding:rxbinding-recyclerview-v7:0.4.0'
}
RxRecyclerViewScrollSubjectを作る
RxRecyclerViewを使ってRecyclerViewScrollEventを受け取り、LinearLayoutManagerを使って最後尾かどうかの判定をします。メソッドは3つだけです。
public class RxRecyclerViewScrollSubject { Subject<RecyclerViewScrollEvent, RecyclerViewScrollEvent> subject = PublishSubject.create(); Subscription subscription = Subscriptions.empty(); public Observable<RecyclerViewScrollEvent> observable() { return subject; } public void start(RecyclerView recyclerView, LinearLayoutManager linearLayoutManager) { subscription.unsubscribe(); subscription = RxRecyclerView.scrollEvents(recyclerView).subscribe(event -> { int totalItemCount = linearLayoutManager.getItemCount(); int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition(); if (totalItemCount - 1 <= lastVisibleItemPosition) { subject.onNext(event); } }); } public void stop() { subscription.unsubscribe(); } }
GridLayoutManagerはLinearLayoutManagerを継承しているのでそのまま使えます。StaggeredGridLayoutManagerは継承関係がないのでfindLastVisibleItemPosition()
が存在せずそのまま使えません。似たようなメソッドがあるので別途StaggeredGridLayoutManagerを受け取る口を作っとくといいかもしれないです。
使う
ライフサイクルに合わせてRxRecyclerViewScrollSubjectをstart()したりstop()します。
public class MainActivity extends AppCompatActivity { RxRecyclerViewScrollSubject rxRecyclerViewScrollSubject = new RxRecyclerViewScrollSubject(); RecyclerView recyclerView; LinearLayoutManager linearLayoutManager; Subscription subscription = Subscriptions.empty(); @Override protected void onCreate(Bundle savedInstanceState) { //省略 } @Override protected void onResume() { super.onResume(); rxRecyclerViewScrollSubject .start(recyclerView, linearLayoutManager); } @Override protected void onPause() { super.onPause(); rxRecyclerViewScrollSubject.stop(); } }
初回の読み込みが終わったらRxRecyclerViewScrollSubject.observable()
をsubscribeし、イベントが来たらunsubscribeして追加読み込みをし、追加読み込みが完了したら再度subscribeするといった使い方になります。
void loadWhenLastPosition(int nextPage) { subscription = rxRecyclerViewScrollSubject.observable().subscribe(event -> { subscription.unsubscribe(); load(nextPage); }); }
追加読み込みを開始したら最後尾のスクロール通知を切り、また通知して欲しくなったらsubscribeする感じです。
最後に
もっとなんかいい方法ある気もしつつ。