我正在尝试使用RemoteMediator实现一个带有分页3库的列表。
初始加载是可以的。中介只加载了3页,设置在“PageConfig”中。在我的例子中,每页有10个数据。
但是,当滚动列表以触发更多数据的额外加载时,Mediator将无限地开始加载数据,直到它返回MediatorResult.Success(endOfPaginationReached = true)
(这意味着远程中的所有数据都已加载)。即使滚动停止了。
我不知道是什么让中介继续加载。
我希望Mediator在滚动过程中加载只需要的数据。
这是我的代码:
@OptIn(ExperimentalPagingApi::class)
class PostRemoteMediator(
private val postApi: ApiInterface,
private val database: PostDatabase
) : RemoteMediator<Int, Post>() {
override suspend fun load(loadType: LoadType, state: PagingState<Int, Post>): MediatorResult {
return try {
val userId = when (loadType) {
LoadType.REFRESH -> {
logd(">> loadType.REFRESH")
STARTING_USER_ID
}
LoadType.PREPEND -> {
return MediatorResult.Success(endOfPaginationReached = true)
}
LoadType.APPEND -> {
logd(">> loadType.APPEND")
val lastItem = state.lastItemOrNull()
?: return MediatorResult.Success(endOfPaginationReached = true)
lastItem.userId + 1
}
}
logd(">> load data with userId = $userId")
val response = postApi.getUserPosts(userId)
database.withTransaction {
if (loadType == LoadType.REFRESH) {
database.postsDao().clearAll()
}
database.postsDao().insertAll(response?.body() ?: emptyList())
}
MediatorResult.Success(
endOfPaginationReached = response.body().isNullOrEmpty()
)
} catch (e: IOException) {
MediatorResult.Error(e)
} catch (e: HttpException) {
MediatorResult.Error(e)
}
}
}
@OptIn(ExperimentalPagingApi::class)
class PostRepositoryImpl @Inject constructor(
private val remoteApi: ApiInterface,
private val database: PostDatabase
) : PostRepository {
override fun getUserPosts(): Flow<PagingData<Post>> {
return Pager(
config = PagingConfig(
pageSize = 1
),
remoteMediator = PostRemoteMediator(
remoteApi,
database
)
) {
// returns all data in table as PagingSource<Int, Post>
database.postsDao().getPosts()
}.flow
}
}
@HiltViewModel
class PostViewModel @Inject constructor(
private val postRepository: PostRepository
) : ViewModel() {
private val TAG = PostViewModel::class.simpleName
val postFlow: Flow<PagingData<Post>> = postRepository.getUserPosts().cachedIn(viewModelScope)
}
这是UI代码:
@Composable
fun PostList(postsFlow: Flow<PagingData<Post>>) {
val posts = postsFlow.collectAsLazyPagingItems()
LazyColumn(contentPadding = PaddingValues(horizontal = 8.dp)) {
items(posts, key = { it.id }) { post ->
post?.also { PostItem(userId = it.userId, id = it.id, content = it.body) }
}
posts.apply {
when {
loadState.mediator?.refresh is LoadState.Loading -> {
item { LoadingView(modifier = Modifier.fillParentMaxSize()) }
}
loadState.mediator?.append is LoadState.Loading -> {
item { LoadingView(modifier = Modifier.wrapContentHeight()) }
}
loadState.mediator?.refresh is LoadState.Error -> {
val error = loadState.refresh as LoadState.Error
item { ErrorView(error.error.localizedMessage!!, modifier = Modifier.fillParentMaxSize()) { retry() } }
}
loadState.mediator?.append is LoadState.Error -> {
val error = loadState.append as LoadState.Error
item { ErrorView(error.error.localizedMessage!!, modifier = Modifier.wrapContentHeight()) { retry() } }
}
}
}
}
}
谢谢你的回答
发布于 2022-08-31 21:33:20
在创建pageSize时增加PageConfig。
根据文件:
应该是屏幕上可见项数的几倍。配置页面大小取决于如何加载和使用数据。较小的页面大小改善了内存的使用、延迟和避免GC的搅动。更大的页面通常会在一定程度上提高加载吞吐量(避免一次从SQLite加载超过2MB的数据,因为这会带来额外的成本)。如果您正在为占用大部分屏幕的非常大的社交媒体样式卡加载数据,而且您的数据库不是瓶颈,那么10-20可能是有意义的。如果您要在平铺网格中显示数十个项目,这样可以更快地在滚动过程中显示项目,请考虑更接近100。
https://stackoverflow.com/questions/73047015
复制相似问题