kotlin Android Paging 3 remoteMediator infinitely load(APPEND)data with Compose

dgiusagp  于 2023-10-23  发布在  Kotlin
关注(0)|答案(2)|浏览(151)

我试图实现一个列表与分页3库使用RemoteMediator。
初始加载正常。Mediator仅加载了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() } }
                }
            }
        }
    }
}

谢谢你的回答

zbdgwd5y

zbdgwd5y1#

在创建PageConfig时增加pageSize。
根据文件:
应该是可见项目数的几倍。配置页面大小取决于加载和使用数据的方式。较小的页面大小可以改善内存使用、延迟,并避免GC扰动。较大的页面通常可以提高加载吞吐量(避免一次从SQLite加载超过2 MB,因为这会产生额外的成本)。如果你加载的数据非常大,社交媒体风格的卡片占据了大部分屏幕,而且你的数据库不是瓶颈,那么10-20可能是有意义的。如果你要在平铺网格中显示几十个项目,这可以在滚动过程中更快地显示项目,考虑接近100个。

3gtaxfhh

3gtaxfhh2#

首先确保initialLoadSize小于在remoteMediator中使用的pageSize,当你将其分配给pageSize时使用larg数字取决于你有多少数据,在我的情况下,我使用15 pagesize,因为我在我的寻呼机中有75个项目,其次使用这种方式在lazy列中显示项目,这对我很有用,

items(animePagingItems.itemCount) { index ->
        val anime= animePagingItems[index]
        if (anime != null) {
            ItemAnime(animeData= anime) {}
        }
    }

相关问题