みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
KotlinのaddOnScrollListenerを使用した無限スクロール機能について
実際のコードを利用して徹底解説していきます!
この記事を読んでわかること…
・無限スクロールとは?
・addOnScrollListenerとは?
・リストの末尾付近で追加データを読み込む「無限スクロール (Infinite Scroll)」の実装方法
RecyclerView
を使用したリスト表示については、以下の記事で詳しくご紹介しておりますので
ぜひ合わせてご覧ください!↓
環境
- Kotlin (ver 1.9.0)
- Android Studio (Giraffe | 2022.3.1 Patch 3)
無限スクロールとは?
無限スクロール(Infinite Scroll)とは、
ユーザーがリストの下にスクロールすると自動的に追加のデータが読み込まれ、リストが継続的に拡張される技術です。
SNSやニュースアプリなどでよく使われており、ユーザー体験(UX)を向上させます。
addOnScrollListenerとは?
addOnScrollListener
は RecyclerView
にスクロールイベントを監視するリスナー(Listener:特定のイベントが発生したときに反応する仕組み)を追加するメソッドです。
これを使うことで、スクロールが一定位置に達したときに「次のデータをロードする」といった処理が可能になります。
無限スクロールの基本的な仕組み
無限スクロールの流れは以下のようになります。
- リストがスクロールされる。
- ユーザーがリストの下端に到達したとき、次のデータを自動的にロードする。
- ロードされたデータを既存のリストに追加して、リストが拡張される。
この動作を実現するために、RecyclerView
に addOnScrollListener
を設定して、
スクロール位置を監視します。
リストの末尾付近で追加データを読み込む「無限スクロール (Infinite Scroll)」の実装方法
それでは早速実装していきましょう!
1. レイアウトファイルの作成
まず、RecyclerView
を含むレイアウトファイルを作成します。
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2. RecyclerViewにリスナーを追加
次に、RecyclerView
にスクロールリスナーを追加します。
class InfiniteScrollListener(
private val layoutManager: LinearLayoutManager,
private val loadMore: () -> Unit
) : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = recyclerView.childCount
val totalItemCount = layoutManager.itemCount
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount - 2) {
loadMore()
}
}
}
サンプルコードの解説
1〜4行目
InfiniteScrollListener
は、RecyclerView.OnScrollListener
を継承しており、RecyclerView
のスクロールイベントを監視するカスタムリスナーです。
- コンストラクタで
layoutManager
(RecyclerView
のレイアウト管理)と、データをロードするための処理をラムダ関数loadMore
で受け取ります。 loadMore
は、スクロールが特定の位置に達したときに実行されるデータ取得処理です。
(APIでデータを取得するなど)
6〜7行目
onScrolled
は RecyclerView
がスクロールするたびに呼ばれるメソッドです。
dx
は水平方向のスクロール量、dy
は垂直方向のスクロール量を示します。dy > 0
→ 下方向へのスクロールdy < 0
→ 上方向へのスクロール
- 下方向にスクロールしたときにのみ無限スクロールが動作するようになっています。
9〜11行目
visibleItemCount
- 現在画面に表示されているアイテムの数。
- 例えば、画面に10個のアイテムが表示されていれば
10
になります。
totalItemCount
RecyclerView
に登録されているすべてのアイテム数を取得します。- InfiniteScrollListener()の引数に リストデータの総数を持たせてtotalItemCountとする、という方法でもよいです。
firstVisibleItemPosition
- 現在画面に表示されている最初のアイテムの位置(インデックス)。
- 例: リストがスクロールされて 5番目のアイテムが最初に表示されていれば
5
になります。
12〜14行目
visibleItemCount + firstVisibleItemPosition
は、画面に表示されている最後のアイテムの位置を示します。
totalItemCount - 2
は、リストの末尾から2つ前のアイテム位置です。- この条件が成立すると、リストの末尾付近に到達したと判断して
loadMore
が呼ばれます。
例)
visibleItemCount = 10、firstVisibleItemPosition = 30、totalItemCount = 42 の場合:
10 + 30 = 40 で、totalItemCount – 2 = 40 なので loadMore()
が呼び出されます。
3. リスナーをRecyclerViewに設定
次に、このリスナーを RecyclerView
に追加します
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = myAdapter // ここでアダプターを設定
recyclerView.addOnScrollListener(
InfiniteScrollListener(recyclerView.layoutManager as LinearLayoutManager) {
fetchMoreData() // 追加データの取得処理
}
)
4. メモリリークを防ぐための処理を追加
RecyclerView
に addOnScrollListener
を追加し続けると、メモリリーク(使い終わったリソースが解放されずメモリを消費し続ける問題)が発生する可能性があります。
これを防ぐために、不要になったリスナーをクリアする必要があります。
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = myAdapter
// 以下の処理を追加
recyclerView.clearOnScrollListners()
recyclerView.addOnScrollListener(
InfiniteScrollListener(recyclerView.layoutManager as LinearLayoutManager) {
fetchMoreData()
}
)
↑リストのデータを更新する前に、clearOnScrollListners()
を置くことで
古いスクロールリスナーを削除してから新しいリスナーを追加することで 二重登録を防ぎます
※ fetchMoreData()はスクロールリスナー内のloadMore()にあたります。
fetchMoreDataが呼ばれるたびに指定の数だけデータを取得できる処理(ページング)を APIなどで実装してください。
それではビルドしてみましょう!
無限スクロール機能が完成しました!
まとめ
おつかれさまでした。いかがでしたでしょうか!
- 無限スクロールは、スクロール位置に応じてデータを自動的に追加する仕組みで、ユーザー体験を向上させる
addOnScrollListener
を使うことで、簡単に無限スクロールが実装できる- メモリリークを防ぐために、リスナーを適切に解除することが重要
上記ぜひ覚えて、アプリ開発で試してみてくださいね〜!
技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
自分の市場価値をさらに向上させてみませんか?
それではまた次の記事でお会いしましょう!
コメント