刷新 LazyPagingItems,而不明显刷新 Jetpack Compose 中的 LazyColumn

问题描述 投票:0回答:2

我正在使用 Jetpack Compose 和 LazyPagingItems 通过 Paging 3 库在 LazyColumn 中显示分页数据。当用户返回选项卡时,我通过调用 PagingSource 上的刷新()来实现刷新功能。

但是,当我在与 LazyPagingItems 关联的 PagingSource 上调用刷新()时,整个 LazyColumn 都会刷新,导致 UI 明显重新加载并滚动回顶部。这种行为并不理想,因为它会破坏用户体验。我只需要该列更新新数据(如果有)。

我想找到一种方法来刷新 LazyPagingItems 中的数据,而不让用户注意到任何可见的更改。换句话说,我想在后台默默地更新数据。

@HiltViewModel
class MainViewModel @Inject constructor(
    private val beersRepository: BeersRepository,
) : ViewModel() {

    val state: Flow<PagingData<Beer>> = beersRepository
        .getBeers()
        .flow
        .cachedIn(viewModelScope)

}

//Repository
class BeersRepository @Inject constructor(
    private val beersApiService: BeersApiService,
) {

    fun getBeers() = Pager(
        config = PagingConfig(
            pageSize = 10,
            enablePlaceholders = true,
        ),
        pagingSourceFactory = { BeersPagingSource(beersApiService = beersApiService) }
    )
}

//Paging source
class BeersPagingSource @Inject constructor(
    private val beersApiService: BeersApiService,
) : PagingSource<Int, Beer>() {

    override fun getRefreshKey(state: PagingState<Int, Beer>): Int? {
        return state.anchorPosition?.let { anchorPosition ->
            state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)
                ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
        }
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Beer> {
        val page = params.key ?: 1
        return try {
            delay(500)
            val response = beersApiService.getBeers(page, perPage = 10)
            if (response.isSuccessful) {
                val beers = response.body()!!.map {
                    it.toDomain()
                }
                LoadResult.Page(
                    data = beers,
                    prevKey = if (page == 1) null else page - 1,
                    nextKey = if (beers.isEmpty()) null else page + 1
                )
            } else {
                LoadResult.Error(Exception(response.message()))
            }
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}


//And finally the Composable
private fun MainScreenRoute(
    viewModel: MainViewModel = viewModel(),
) {
    val pagingItems = viewModel.state.collectAsLazyPagingItems()

    Scaffold(bottomBar = {
        Row(
            modifier = Modifier
                .background(Color.Transparent)
                .fillMaxWidth(),
            horizontalArrangement = Arrangement.Center
        ) {
            Button(onClick = {
                pagingItems.refresh()
            }) {
                Text(
                    text = "Refresh", style = MaterialTheme.typography.bodyLarge
                )
            }
        }
    }) {
        Surface {
            Column(
                modifier = Modifier.fillMaxSize()
            ) {
                when (pagingItems.loadState.refresh) {
                    is LoadState.Error -> {

                    }

                    LoadState.Loading -> {
                        Surface {
                            Box(
                                contentAlignment = Alignment.Center,
                                modifier = Modifier.fillMaxSize()
                            ) {
                                Text(
                                    text = "Loading...",
                                    style = MaterialTheme.typography.headlineLarge
                                )
                            }
                        }
                    }

                    is LoadState.NotLoading -> {
                        LazyColumn(
                            verticalArrangement = Arrangement.spacedBy(8.dp),
                            contentPadding = PaddingValues(8.dp)
                        ) {
                            items(pagingItems.itemCount) { index ->
                                val beer = pagingItems[index]!!
                                BeerCard(
                                    imageUrl = beer.image,
                                    name = beer.name,
                                    description = beer.description,
                                )
                            }
                        }
                    }
                }

            }
        }
    }
}

已在

refresh()
上尝试
LazyPagingItems

android android-jetpack-compose android-paging-3 android-jetpack-compose-lazy-column
2个回答
1
投票

您是否在 ViewModel 中缓存了

giftsList
?它应该看起来像这样:

val giftsList = repository.giftsList.cachedIn(viewModelScope)


0
投票

我知道这是一个老问题,但我想分享我的解决方案。 我最终将列表放入其自己的可组合项中,然后设置它将响应哪些状态更改。 cachedIn 解决方案对我不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.