SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門

「ページングライブラリ」でネット上のリストデータをページングする方法

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門 第13回

PagingSourceクラスの自作が必要(2)

getRefreshKey()メソッドの実装方法

 PagingSourceクラスでは、もうひとつgetRefreshKey()メソッドをオーバーライドしておく必要があります。このメソッドは、リフレッシュなど、現在表示されているページデータが何らかの形で失われた場合に、どのリストデータを次に表示させればいいかの処理を記述します。

 例えば、id(=キー)が200までのリストデータがページとして格納された状態で、そのうち120~130の10件が画面に表示されているとします。その状態で、何らかの理由でリストデータが失われたとします。その場合にスクロールが始まると、130以降のデータを取得しておく必要があります。

 この開始キーを決めるのが、getRefreshKey()メソッドであり、例えば、リスト3のコードとなります。

[リスト3]getRefreshKey()メソッドのコード例
override fun getRefreshKey(state: PagingState<Int, Phone>): Int? {
  var returnVal: Int? = null;  // (1)
  val anchorPosition = state.anchorPosition  // (2)
  if(anchorPosition != null) {  // (3)
    val phone = state.closestItemToPosition(anchorPosition)  // (4)
    if(phone != null) {  // (5)
      val returnKey = phone.id.toInt() - state.config.pageSize / 2  // (6)
      if(returnKey > 0) {  // (7)
        returnVal = returnKey
      }
    }
  }
  return returnVal
}

 先述のように、getRefreshKey()メソッドの働きは、データが失われた際に再取得の開始キーを決めるメソッドです。従って、メソッド内の処理によって決定された開始キーを戻り値とします。そして、この戻り値の値が、そのままload()メソッドの引数paramsのkeyプロパティとして渡されます。もちろん、nullを戻り値とすることもでき、その場合は、nullがkeyプロパティとして渡されます。

 リスト3の大きな流れとしては、リストデータが失われる前にどのデータが画面に表示されていたかを取得し、そこからid(=キー)の値を割り出します。割り出したidから1ページの表示件数の半分だけ戻ったid値を戻り値とする、といったコードです。

 先の例で説明するならば、まずidが123あたりのデータを見ていたとし、そこから25(50件/ページの半分)戻った値、つまり、98を戻り値とします。結果、load()メソッドでは、この98という値をstartKeyとして、データを再取得することになり、画面がスクロールされてもスムーズに表示されるようになります。

 ただし、随所にデータが取得できないことが考えられ、そのためのnull処理コードが必要となります。そして、データが取得できない場合は、そもそもgetRefreshKey()の戻り値もnullとし、結果、load()メソッドでは初期リストデータを用意するようにします。

 これを踏まえ、(1)で戻り値変数であるreturnValを初期値nullとして用意しています。次に、引数であるPagingStateオブジェクトのプロパティanchorPositionを利用して、画面に表示されていたポジション値を取得します。それが、リスト3の(2)です。この値は、あくまでリストのポジションであって、id(=キー)の値ではありません。

 そこで、ポジションに基づくアイテムオブジェクト(この場合はPhoneオブジェクト)を取得するために、同じくPagingStateのclosestItemToPosition()メソッドを利用します。それが、リスト3の(4)です。ただし、anchorPositionがnullの可能性を考慮して(3)のコードが必要です。

 同様に、取得したアイテムオブジェクト(=Phoneオブジェクト)もnullの可能性があるので、そのチェックを(5)で行った上で、ようやくidの値を取得します。

 そのidの値から1ページの表示件数の半分を引き算しているのが(6)です。ただし、この値は、場合によっては0以下になることもあり得ます。そのためのチェックを行っているのが(7)であり、ここまでの条件をクリアして、ようやく戻り値のreturnValとできます。これ以外は、全てnullがリターンされるようになります。

自作PagingSourceクラスの使い方はRoomと同じ

 このようにして自作したPagingSourceクラスを利用する方法は、RoomのDAOオブジェクトから取得したPagingSourceオブジェクトと同じです。リスト4のように、Pagerインスタンスを生成する際の第2引数としてPagingSourceオブジェクトをリターンするラムダ式内で、自作のPagingSourceインスタンスを生成するだけです。

[リスト4]自作したPagingSourceを元にPagerを生成するコード例
val phoneListPager = Pager(pagingConfig) {PhonePagingSource()}

次のページ
JavaでのPagingSourceクラスの作り方

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

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

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

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/21204 2025/03/27 11:00

イベント

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

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

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

メールバックナンバー