Skip to main content

JetpackComposeでPaging3を使ってみた

今回はJetpackComposeでページングとして
Paging3を利用したときに学んだことをまとめる


・パッケージ
paging-composeのstableがなくてウケる
rc版ならまぁ問題ないと思うけど
https://zenn.dev/sobya/articles/1fdf9c92bb4404

implementation "androidx.paging:paging-runtime-ktx:2.6.0"
implementation "androidx.paging:paging-compose:3.2.0-rc01"

 

・PagingSource
getRefreshKeyをnullにするとrefresh関数を呼ぶと初期化される
loadのprevKeyとnextKeyは読み込みに成功したときに次のページの場所を伝える
https://tech.pepabo.com/2021/10/18/android-paging3/

class PagingSource(
    private val api: API,
) : PagingSource<Int, Model>() {
    override fun getRefreshKey(state: PagingState<Int, Model>): Int? {
        return null
    }
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Model> {
        return try {
            val pager = params.key ?: 1
            val response = api.exec(pager)
            LoadResult.Page(
                data = response,
                prevKey = (pager - 1).takeIf { key -> key > 0 },
                nextKey = (pager + 1).takeIf { _ -> response.isNotEmpty() }
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

・PagingSourceその2
ページングなしの場合は以下にする

LoadResult.Page(
    data = response,
    prevKey = null,
    nextKey = null
)

 

・ViewModel
pagingSizeで一ページの数を渡す

val pager = Pager(PagingConfig(pageSize = 100)) {
    PagingSource(api)
}.flow.cachedIn(viewModelScope)

 

・View
データをLazyColumnに渡すだけ
ページングとか先読みとかは勝手にやってくれる
すげー便利
https://proandroiddev.com/pagination-in-jetpack-compose-with-and-without-paging-3-e45473a352f4

val list = viewModel.pager.collectAsLazyPagingItems()
LazyColumn {
    items(
        count = list.itemCount,
        key = list.itemKey { it },
        contentType = list.itemContentType { "Model名" }
    ) { index ->
        val model = list[index] ?: return@items
    }
}

・paging3の更新
https://zenn.dev/portinc/articles/understand_android_pager3

val list = viewModel.pager.collectAsLazyPagingItems()
list.refresh()

・リスト更新時
更新したときにスクロール位置が自動で戻らないないので・・・
stateで上に戻しましょう

val listState = rememberLazyListState()
LaunchedEffect(Unit) {
    listState.scrollToItem(0)
}
LazyColumn(state = listState) {
    //hogehoge
}

・paging3のエラーハンドリング
https://zenn.dev/portinc/articles/understand_android_pager3
どこの読み込みかでエラーを見る場所が違うので注意
ページングの読み込み時はフッターにボタンつけたりするのはすごく楽

val refreshLoadState = list.loadState.refresh // 更新時
val prependLoadState = list.loadState.prepend // 前データ
val appendLoadState = list.loadState.append // 追加時

//ロード中
refreshLoadState == LoadState.Loading
//エラー
refreshLoadState is LoadState.Error
//読み込み終了
loadState == LoadState.NotLoading(true))

関連記事:

Pocket