にんにんにん

エンジニアな日々を書いていきます

JetpackCompose + Paging3でPaging実装

Paging3を使用。JetpackCompose用のオプションがあるので、build.gradleに追加する。

    // optional - Jetpack Compose integration
    implementation "androidx.paging:paging-compose:1.0.0-alpha15"

Paging3の実装に則り、PagingSourceを定義。 この辺はcodelabを見るとわかりやすい。

Android のページングの基本  |  Android Developers

class SamplePagingSource : PagingSource<Int, String>() {
    companion object {
        const val STARTING_KEY = 0
    }
    override fun getRefreshKey(state: PagingState<Int, String>): Int = 0

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, String> {
        val start = params.key ?: STARTING_KEY
        val range = start.until(start + params.loadSize)
        delay(3000L)
        return LoadResult.Page(
            data = range.map { number ->
                number.toString()
            },
            prevKey = when (start) {
                STARTING_KEY -> null
                else -> ensureValidKey(range.first - params.loadSize)
            },
            nextKey = range.last + 1
        )
    }
}

そして、Pagerを作成。 本来であればViewModel等でPagerを持つことになりそう。

    val pager = Pager(
        PagingConfig(10, enablePlaceholders = false),
        pagingSourceFactory = {
            SamplePagingSource()
        }
    )

そして、ここからがJetpackComposeの話になるが、collectAsLazyPagingItems()を使って、PagerをLazyPagingItemsに変換する。

val lazyPagingItems = pager.flow.collectAsLazyPagingItems()

developer.android.com

LazyColumnに追加する。

    LazyColumn(
        modifier = Modifier
            .fillMaxWidth()
            .nestedScroll(nestedSrollInterop)
    ){
        items(
            items = lazyPagingItems,
            key = { message -> message }
        ) { item ->
            Box(
                modifier = Modifier
                    .height(56.dp)
                    .fillMaxWidth()
                    .background(Color.Gray),
                contentAlignment = Alignment.Center
            ) {
                Text(item.toString())
            }
        }
     }
     item {
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                CircularProgressIndicator()
            }
     }

必要に応じて、下部にCircularProgressIndicator()を追加してあげると良い。

動作させるとこんな感じ。