Paging Library + API + データ追加/削除

Kenji Abe
Kenji Abe
Sep 2, 2018 · 3 min read

データ追加/削除が絡む、Paging Library + APIは単純にはいかないので、工夫が必要です。

Paging Library自体の説明は省略します。

環境

implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0-rc01'
implementation 'androidx.paging:paging-runtime:2.0.0-rc01'
implementation 'androidx.room:room-runtime:2.0.0-rc01'
kapt 'androidx.room:room-compiler:2.0.0-rc01'

問題点

PagedList は基本的にあとから追加/削除ができず、データを追加したり、削除したりする場合は、再生成する必要があります。

ほとんどのケースでAPI通信の場合は、 PageKeyedDataSourceItemKeyedDataSource を使うことになると思います。

DataSource#invalidate で、単純に再生成すると、1ページ目から取得することになります。例えば、5ページ目にあるデータを削除した場合にまた1ページ目が表示されてしまう感じになってしまいます。

解決策

こういった問題はRoomを組み合わせることで解決することができます。Roomをキャッシュに使うような実装とほぼ同じです。

PagingのDataSourceにはRoomを使い、APIから取得したデータをRoomへ書き込んでいきます。
データ追加/削除が必要なときは、APIへリクエストしつつ、Room側のデータを追加/削除することで、表示も問題なく行うことが可能になります。

以下に実装時のポイントを少しだけ。

実装ポイント

BoundaryCallback

Paging Libraryには BoundaryCallback というものがあり、 PagedList が最後まで来た場合に通知をしてくれるものです。

これを使うことで、RoomのデータがないときにAPI通信を行いRoomへ書き込む処理が可能になります。

以下のような感じになってます。

これを LivePagedListBuilder#setBoundaryCallback に渡すと通知が来るようになります。

RoomのPaging

RoomはPagingに対応していて、Roomの実装自体は簡単にできます。

Daoでクエリの戻り値に DataSource.Factory を指定することでPaging可能になります。

RoomのPagingはデータの変更を監視していて、データの変更が行われると、 DataSource#invalidate が呼ばれて、 PagedList が再生成される様になっています。(コード

また、RoomのDataSourceには PositionalDataSource が使われていて、 loadInitial で必要なポジションとページサイズを求めて取得するようになっています。(コード

サンプル

簡単なサンプルを作りました。Redditからデータ取得して、Deleteボタンで行削除ができるやつです。

data.repository パッケージ内を見てもらえるとだいたい分かるかなと。

Kenji Abe

Written by

Kenji Abe

Programmer / Gamer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade