You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin LazyPagingItems itemCount初始值为0的问题及优化方案问询

LazyPagingItems初始itemCount为0的问题优化方案探讨

在使用Paging3将PagingData收集为LazyPagingItems时,存在一个疑似Bug:LazyPagingItems的itemCount初始值始终为0。如果直接通过该参数控制列表或空状态提示的显示,初始阶段会错误触发空列表分支。

问题代码示例

Box(
    modifier = Modifier
        .padding(innerPadding)
        .nestedScroll(scrollBehavior.nestedScrollConnection)
        .fillMaxSize()
) {
    when (val state = homeScreenUiState.homeScreenMovieListState) {
        is HomeScreenMovieListState.Error -> {
            LoadingMovieDataImageDisplay(
                modifier = Modifier.align(Alignment.Center),
                image = R.drawable.movie_list_loading_error,
                message = state.message
            )
        }

        is HomeScreenMovieListState.Loading -> {
            LoadingMovieDataLoadingDisplay(modifier = Modifier.align(Alignment.Center))
        }

        is HomeScreenMovieListState.Success -> {
            val movieList = state.movieList.collectAsLazyPagingItems()
            when {
                movieList.itemCount > 0 -> {
                    HomeMovieList(
                        movieList = movieList,
                        navigateToMovieDetails = navigateToMovieDetails,
                        lazyGridState = lazyGridState,
                        paddingValues = PaddingValues(
                            top = movieListPaddingValues.value,
                            start = 10.dp,
                            end = 10.dp,
                            bottom = 10.dp,
                        )
                    )
                }

                movieList.itemCount == 0 -> {
                    LoadingMovieDataImageDisplay(
                        modifier = Modifier.align(Alignment.Center),
                        image = R.drawable.movie_list_loading_error,
                        message = R.string.movie_list_connection_lost,
                    )
                }
            }
        }
    }
}

临时解决方案

通过添加LoadState检查,避免初始加载时误判为空列表:

when {
    movieList.itemCount > 0 -> {
        HomeMovieList(
            movieList = movieList,
            navigateToMovieDetails = navigateToMovieDetails,
            lazyGridState = lazyGridState,
            paddingValues = PaddingValues(
                top = movieListPaddingValues.value,
                start = 10.dp,
                end = 10.dp,
                bottom = 10.dp
            ),
        )
    }

    movieList.itemCount == 0 && movieList.loadState.refresh != LoadState.Loading -> {
        LoadingMovieDataImageDisplay(
            modifier = Modifier.align(Alignment.Center),
            image = R.drawable.movie_list_loading_error,
            message = R.string.movie_list_connection_lost,
        )
    }
}

更优解决方案探讨

1. 基于LoadState的完整状态流转判断

直接以loadState为核心判断不同状态,逻辑更清晰,避免依赖itemCount的初始值问题:

val movieList = state.movieList.collectAsLazyPagingItems()
when {
    movieList.loadState.refresh is LoadState.Loading -> {
        // 初始加载中,显示加载组件
        LoadingMovieDataLoadingDisplay(modifier = Modifier.align(Alignment.Center))
    }
    movieList.loadState.refresh is LoadState.Error -> {
        // 初始加载失败,显示错误组件
        LoadingMovieDataImageDisplay(
            modifier = Modifier.align(Alignment.Center),
            image = R.drawable.movie_list_loading_error,
            message = (movieList.loadState.refresh as LoadState.Error).error.localizedMessage
        )
    }
    movieList.itemSnapshotList.isEmpty() -> {
        // 加载完成且无数据,显示空列表提示
        LoadingMovieDataImageDisplay(
            modifier = Modifier.align(Alignment.Center),
            image = R.drawable.movie_list_loading_error,
            message = R.string.movie_list_connection_lost,
        )
    }
    else -> {
        // 有数据,显示列表
        HomeMovieList(
            movieList = movieList,
            navigateToMovieDetails = navigateToMovieDetails,
            lazyGridState = lazyGridState,
            paddingValues = PaddingValues(
                top = movieListPaddingValues.value,
                start = 10.dp,
                end = 10.dp,
                bottom = 10.dp
            ),
        )
    }
}

2. 使用itemSnapshotList替代itemCount

itemSnapshotList是LazyPagingItems当前加载数据的不可变快照,它的isEmpty()能更准确反映实际数据状态,结合加载状态判断更可靠:

val snapshot = movieList.itemSnapshotList
if (snapshot.isEmpty() && movieList.loadState.refresh !is LoadState.Loading) {
    // 显示空列表提示
} else if (movieList.loadState.refresh is LoadState.Loading) {
    // 显示加载中
} else {
    // 显示列表
}

3. 封装状态判断扩展函数

将重复的状态判断逻辑抽成扩展函数,提升代码复用性和可读性:

fun <T : Any> LazyPagingItems<T>.isLoading(): Boolean {
    return loadState.refresh is LoadState.Loading
}

fun <T : Any> LazyPagingItems<T>.hasError(): Boolean {
    return loadState.refresh is LoadState.Error
}

fun <T : Any> LazyPagingItems<T>.isEmptyAfterLoad(): Boolean {
    return itemSnapshotList.isEmpty() && !isLoading()
}

使用时直接调用:

when {
    movieList.isLoading() -> LoadingMovieDataLoadingDisplay(...)
    movieList.hasError() -> LoadingMovieDataImageDisplay(...)
    movieList.isEmptyAfterLoad() -> LoadingMovieDataImageDisplay(...)
    else -> HomeMovieList(...)
}

目前上述临时方案可解决问题,期待Google在Paging3后续版本中修复itemCount初始值的问题。

内容的提问来源于stack exchange,提问作者hbjosemaria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:28:09