Android 使用 Jetpack Compose 无需滚动即可无限加载 Paging 3 库
Android Paging 3 library loading infinitely without scroll with Jetpack Compose
我正在尝试使用 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)
}
}
}
这是 UI:
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 Books 经常搜索 return 数千个结果,但即使我不滚动屏幕它也会这样做。
这里的问题是我在 LazyColumn
中创建元素的方式 - 它本身支持 LazyPagingItem
但我没有使用它。这是工作版本:
LazyColumn(
modifier = Modifier.padding(horizontal = 24.dp),
state = listState,
content = {
items(pagedSearchResults) { book ->
book?.let {
BookCard(
book = book,
navigateToBookDetail = { navigateToBookDetail(book.id) }
)
}
}
}
)
在您的原始示例中,您必须使用 peek 检查 non-null 并访问列表,就像您仅在 inside 项目块,这是惰性的。否则分页功能将丢失,它将一次性加载整个数据集。
我正在尝试使用 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)
}
}
}
这是 UI:
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 Books 经常搜索 return 数千个结果,但即使我不滚动屏幕它也会这样做。
这里的问题是我在 LazyColumn
中创建元素的方式 - 它本身支持 LazyPagingItem
但我没有使用它。这是工作版本:
LazyColumn(
modifier = Modifier.padding(horizontal = 24.dp),
state = listState,
content = {
items(pagedSearchResults) { book ->
book?.let {
BookCard(
book = book,
navigateToBookDetail = { navigateToBookDetail(book.id) }
)
}
}
}
)
在您的原始示例中,您必须使用 peek 检查 non-null 并访问列表,就像您仅在 inside 项目块,这是惰性的。否则分页功能将丢失,它将一次性加载整个数据集。