みなさんPaging使ってますか?
公式ドキュメントを見ると、LiveDataを使わずにRxJava2を使用しても良いということだったのですが、いまいちどのように実装するのかがよくわからず試行錯誤した結果を書き残したいと思います。
前提
- 以下の条件の方々を読者と仮定します
- AAC Pagingがどのようなものか大体わかる
- これからPagingを導入しようと思っている
- LiveDataは導入していない
やること
AndroidXの場合
DataSourceFactory#toObservableでPagedListのObservableを作成する
or
LivePagedListBuilderを使うかわりにRxPagedListBuilderを使う
AndroidXじゃない場合
LivePagedListBuilderを使うかわりにRxPagedListBuilderを使う
まず、PagingのRxサポートはオプショナルなのでbuild.gradleに追加で記述が必要になります。
また、AndroidXでtoObservableしたい場合はktxも入れる必要があります
implementation "androidx.paging:paging-runtime:$paging_version"
implementation "androidx.paging:paging-runtime-ktx:$paging_version"
implementation "androidx.paging:paging-rxjava2:$paging_version"
implementation "androidx.paging:paging-rxjava2-ktx:$paging_version"
AndroidXでtoObservableを使う場合は公式のドキュメントを見れば困ることは特にないと思います。
RxPagedListBuilderを使用する場合はFactoryクラスとConfigをBuilderに突っ込めばOKです
lateinit var pagedList: Observable<PagedList<YourObj>>
fun setupPage() {
val config = PagedList.Config.Builder()
.setInitialLoadSizeHint(YOUR_LOAD_SIZE)
.setPageSize(YOUR_PAGE_SIZE)
.setEnablePlaceholders(false)
.build()
//DataSource.Factoryの継承クラス
val factory = YourFactory()
pagedList = RxPagedListBuilder(factory, config)
.buildObservable()
}
こうしてできたObservableをサブスクライブして、onNextに入ってくるPagedListをsubmitしていくという寸法です。
ハマったところ
NestedScrollView内のRecyclerViewをPagingするとバグる
私がやった時はヘッダーが必要だったので、以下のようなレイアウト構成で実装しようと思っていました
- NestedScrollView
- LinerLayout
- TextView < これがヘッダー
- RecyclerView < ここでPaging
- LinerLayout
ところが、このようにすると一度に全てのデータを読み込み、表示しようとしてしまうので動作が極端に重くなります。
PagingのSampleに同様のissueが建てられていましたが、どうも解決しなさそうです(RecyclerViewの仕様?)
うまくPagingを動作させつつスクロール部分の表示を要素にとって変えたい時には、サボらずに一つのRecyclerViewでViewHolderを切り替えて表示を出し分ける必要があるようです。
RxPagedListBuilderのSchedulerの扱い
RxPagedListBuilderで作成したObservableは特別subscribeOnとobserveOnを記述する必要がありません。(別途設定は可能 ドキュメント参照)
気を付けなければならないのはDataSourceがBuilderで設定したSchedulerのスレッド配下であるということです。
私の場合、DataSource内で通信して追加データを取得する際に、RetrofitでSingleを返すようにしていましたが、ワーカースレッドの入れ子状態になるために正常に結果が返ってこない自体に陥りました。
そのため、DataSource内の通信ではCallを使用することで回避しました。