SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

アプリケーション開発の最新トレンド

Androidのページング処理のライブラリ「Paging 3」の移行と実装のポイント

  • X ポスト
  • このエントリーをはてなブックマークに追加

おわりに

 Paging 3の基本的な使い方は以上になります。いかがでしたでしょうか。とっかかりはだいぶ難しそうに感じますが、冒頭で説明したデータの流れを理解すると直感的に記述できると思います。

 これまで、Stateなどを実装するために独自のResult型を定義してその中にPagerのデータとStateを格納するといった実装も見られました。

 しかし、Paging 3を用いることで、PagerやLiveData、Flowなどを返却するだけで済むため、Architectureを守るためにモジュールごとにResult型などを定義するといったことをする必要が無くなります。

 個人的には、このPagerに処理や必要なクラスがまとめられていて、なおかつLiveDataやFlowでデータのみを提供できるといった部分が一番魅力的なポイントだと感じました。

 理解が難しかった点としては、やはりRemoteMediatorのLoadTypeだと思います。従来のPaging 2などでは、初期読み込みと追加読み込みの関数がありボイラープレートとはいえ関数の目的がはっきりしているためわかりやすいです。

 しかし、RemoteMediatorのloadでは上記のボイラープレートをなくすため、LoadTypeによって読み込むpageを決定します。その際の、REFRESH、PREPEND、APPENDのpageに指定すべきかといった部分がCodeLabなどをやるだけでは理解がなかなか難しかったように思います。そのため、今回はRemoteMediatorを分解して解説を行いました。

 個人的には、LoadTypeを一つひとつ理解して、それを踏まえ要件をしっかり認識していたらどのようにpageを指定すべきかわかりやすかったように思います。

 Paging 3を使用することで、よりシンプルで拡張性が高く、プロジェクトに新規参入した人も理解しやすいようなコードに書き換えていけると思います! Androidを楽しみましょう!

補足:発展的な内容

ソートやクエリなどのパラメータを変えたときに再度Pagingを呼び出してデータを取り直す方法

 再読み込みをするだけなら、ほかのPagerを使用して読み出しを始めた際にPaging 3のほうで既存のデータ取得をキャンセルしてから新しい方のPagerの呼び出しを始めてくれるためとても簡単です。ソートやクエリなどはViewModel側で持ちますので、sessionIdなどを含めてViewModelから渡してあげる必要があります。

 そこで、Repositoryの内部でsessionIdを生成していたのですが、ViewModelで生成して渡すようにします。クエリなどを渡す場合は適宜RemoteMediatorやAPIをクエリが渡せるよう実装してください。そして、データを取り直す際にsessionIdを変更してあげることで新しいクエリでデータを取得できるようになります。

 さらに、上記で必須ではないsessionIdを作ったことがここで活きてきますが、sessionIdでDBから読み込んでいるため過去のデータが残っていたとしても読み込まれることがありません。それによって、古いデータが表示されることや、ちらつきといった部分も軽減することができます。

 今回はよりシンプルにするためにsessionIdのみのQueryにしていますが、ここにAPIに指定するSortなどを追加してください。

SampleQuery.kt
data class SampleQuery(
    val sessionId: String = UUID.ramdomUUID().toString()
)

 次に、Repositoryの内部で作成していたsessionIdを引数で渡すように変更します。

AnimeRepository.kt
// 変更前
fun getAnime(): Pager<Int, Anime> {
    val sessionId = UUID.randomUUID().toString()

// 変更後
fun getAnime(query: SampleQuery): Pager<Int, Anime> {

 クエリをLiveDataでもち、switchMapを使いRepositoryのgetAnimesを呼ぶことで、Queryに変更があると再度getAnimesがトリガーされ、新たに読み込みが始まるためクエリに変更があると再度データを取得する実装が実現できます。

AnimeViewModel.kt
// クエリ
private var query = SampleQuery(
    sessionId = UUID.ramdomUUID().toString()
)
// animeListをFragmentでobserveしてAdapterにsubmitする
val animeList: LiveData<PagingData<Anime>> = query.switchMap { changedQuery ->
    animeRepository.getAnimes(changedQuery).liveData
}

fun updateQuery() {
    query.value = SampleQuery(UUID.randomUUID().toString())
    /**
     * 複数Queryに値がある場合はcopyを使用すると、指定個所のみ値を変更できるため便利です
     *
     * query.value = query.value?.copy(sessionId = UUID.randomUUID().toString(), hoge = huga)
     */
}

StateAdapterを使ってデータ読み込み中などの情報を取得する方法

 Paging 3のメリットで挙げていましたが、Paging 3ではローディングなどの状態を取得することができます。具体的な方法としては、FragmentでPagingDataAdapterを継承したAdapterにaddLoadStateListenerをセットすることでLoadStateを取得することができます。

 今回は、初期読み込みでロード中ならプログレスバーを表示、追加読み込みでエラーの場合はエラービューを表示します。

 具体的な実装は以下になります。

adapter.addLoadStateListener { loadState ->
    binding.progressBar.visibility =
        if (loadState.refresh is LoadState.Loading) VISIBLE else GONE

    val errorState = loadState.source.append is LoadState.Error 
        || loadState.mediator?.append is LoadState.Error
    
    binding.errorView.visibility =
        if (errorState) VISIBLE else GONE

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
アプリケーション開発の最新トレンド連載記事一覧

もっと読む

この記事の著者

長濱 伶(ヤフー株式会社)(ナガハマ レイ)

 2000年沖縄県生まれ。 学生時代に計算機シミュレーションを用いた文化の安定性に関する研究に従事。 2021年3月に沖縄工業高等専門学校のメディア情報工学科卒業後、4月にヤフー株式会社に入社。 2021年7月からPayPayフリマのAndroidアプリ開発に携わる。 Twitter: @Fel1Tech

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/15314 2022/02/17 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング