使用 Jetpack Compose 无限加载 Android Paging 3 库而无需滚动

Posted

技术标签:

【中文标题】使用 Jetpack Compose 无限加载 Android Paging 3 库而无需滚动【英文标题】:Android Paging 3 library loading infinitely without scroll with Jetpack Compose 【发布时间】:2022-01-05 22:09:30 【问题描述】:

我正在尝试使用 Jetpack Compose 和 android 的 Paging 3 库制作分页图书列表。我可以制作分页列表并获取数据,但我的分页数据源的load() 函数被无限调用,无需我滚动屏幕。

我的分页数据源如下所示:

class GoogleBooksBookSource @Inject constructor(
    private val googleBooksRepository: GoogleBooksRepository,
    private val query: String
): PagingSource<Int, Book>() 

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Book> 
        val position = params.key ?: 0
        return try 
            val response = googleBooksRepository.searchForBookStatic(query, position)
            if (response is Result.Success) 
                LoadResult.Page(
                    data = response.data.items,
                    prevKey = if (position == 0) null else position - 1,
                    nextKey = if (response.data.totalItems == 0) null else position + 1
                )
             else 
                LoadResult.Error(Exception("Error loading paged data"))
            
         catch (e: Exception) 
            Log.e("PagingError", e.message.toString())
            return LoadResult.Error(e)
        
    

    override fun getRefreshKey(state: PagingState<Int, Book>): Int? 
        return state.anchorPosition?.let  anchorPosition ->
            val anchorPage = state.closestPageToPosition(anchorPosition)
            anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
        
    

这是用户界面:

Column() 
    // other stuff
    LazyColumn(
        modifier = Modifier.padding(horizontal = 24.dp),
        content = 
            for (i in 0 until searchResults.itemCount) 
                searchResults[i]?.let  book ->
                    item 
                        BookCard(
                            book = book,
                            navigateToBookDetail =  navigateToBookDetail(book.id) 
                        )
                    
                
            
        
    )

据我所知,数据加载正确且顺序正确,但是当我记录 API 请求 URL 时,它会进行无限调用,每次都会增加 startIndex。如果我正在滚动,那会很好,因为 Google 图书搜索通常会返回数千个结果,但即使我不滚动屏幕,它也会这样做。

【问题讨论】:

可以尝试调试一下getRefreshKey()是否一直在运行?我猜你的代码是正确的,只是这个函数似乎有问题 getRefreshKey() 没有被重复调用,但load() 是。没有我滚动屏幕,onRefreshKey() 中的state.anchorPosition 有数百个 【参考方案1】:

这里的问题是我在 LazyColumn 中创建元素的方式 - 它本身支持 LazyPagingItem 但我没有使用它。这是工作版本:

LazyColumn(
    modifier = Modifier.padding(horizontal = 24.dp),
    state = listState,
    content = 
        items(pagedSearchResults)  book ->
            book?.let 
                BookCard(
                    book = book,
                    navigateToBookDetail =  navigateToBookDetail(book.id) 
                )
            
        
    
)

【讨论】:

以上是关于使用 Jetpack Compose 无限加载 Android Paging 3 库而无需滚动的主要内容,如果未能解决你的问题,请参考以下文章

Jetpack Compose 实现波浪加载效果

如何从 Jetpack Compose 中的 URL 加载图像? [复制]

Jetpack Compose 中的动态加载插件化技术探索

如何从 Jetpack compose 中的 drawable 加载图像?

社区说 | Jetpack Compose 解析及实践

在 Android 中输入/加载基于 Jetpack Compose 的屏幕时从网络或数据库获取数据