Jetpack compose - 加载更多数据或分页,LazyVerticalStaggeredGrid/LazyColumn 消失

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

每当 LazyVerticalStaggeredGrid/LazyColumn 到达末尾/最后一项时,我都会实现分页或加载更多数据。一切都按预期工作,但是,当数据加载更多功能时,LazyVerticalStaggeredGrid 会关闭屏幕并仅显示加载程序,一旦加载更多数据,LazyVerticalStaggeredGrid 就会再次显示。我不确定我在这里做错了什么。为了更好地理解,我附上了下面的代码。

 Column {
            val dataFlow = viewModel.uiStateFlow.collectAsStateWithLifecycle()

            if (dataFlow.value.error is Throwable) {
                Log.d(TAG, "View: Error")
                Toast.makeText(
                    LocalContext.current,
                    dataFlow.value.error.toString(),
                    Toast.LENGTH_LONG
                ).show()
            } else {
                Log.d(TAG, "View: listview")
                PhotosGrid(
                    modifier = Modifier
                        .fillMaxWidth()
                        .fillMaxHeight(),
                    list = dataFlow.value.list,
                    loading = dataFlow.value.loading
                ) {
                    viewModel.getPhotos()
                }
            }
        }

@Composable
fun PhotosGrid(
    modifier: Modifier,
    lazyListState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
    list: List<PhotosModel>,
    loading: Boolean = false,
    loadMore: () -> Unit
) {
    val reachedBottom: Boolean by remember { derivedStateOf { lazyListState.reachedBottom() } }

    if (reachedBottom && !loading) {
        Log.d(TAG, "View: reached bottom")
        loadMore()
    }

    LazyVerticalStaggeredGrid(
        modifier = modifier,
        columns = StaggeredGridCells.Fixed(2),
        horizontalArrangement = Arrangement.spacedBy(4.dp),
        verticalItemSpacing = 4.dp,
        contentPadding = PaddingValues(all = 4.dp),
        state = lazyListState
    ) {
        items(list) {
            PhotosItem(photosModel = it)
        }
        if (loading) {
            item {
                CircularProgressIndicator(
                    modifier = Modifier.width(64.dp),
                    color = MaterialTheme.colorScheme.secondary
                )
            }
        }
    }
}
@Composable
fun PhotosItem(photosModel: PhotosModel) {
    val imgUrl = photosModel.urls?.regular
    Box {
        AsyncImage(
            model = ImageRequest.Builder(LocalContext.current)
                .data(imgUrl)
                .crossfade(true)
                .build(),
            error = painterResource(R.drawable.broken_image),
            placeholder = painterResource(R.drawable.ic_loader),
            contentDescription = photosModel.description,
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight()
                .clip(RectangleShape)
        )
    }
}
internal fun LazyStaggeredGridState.reachedBottom(buffer: Int = 1): Boolean {
    val lastVisibleItem = this.layoutInfo.visibleItemsInfo.lastOrNull()
    return lastVisibleItem?.index != 0 && lastVisibleItem?.index == this.layoutInfo.totalItemsCount - buffer
}

ViewModel 中的逻辑

 var pageNo = 0


    private val _uiStateFlow = MutableStateFlow(UiState(false, emptyList(), null))
    val uiStateFlow: StateFlow<UiState> = _uiStateFlow

    init {
        viewModelScope.launch {
            photosRepository.getAllPhotos().collectLatest { list ->
                if (list.isEmpty()) {
                    getPhotos()
                } else {
                    _uiStateFlow.update { UiState(list = list) }
                }
            }
        }
    }

    fun getPhotos() = viewModelScope.launch {
        photosRepository.getPhotos(accessKey = ConstantUrls.ACCESS_KEY, pageNo = pageNo++) { event ->
            when(event) {
                is ResponseEvent.Failure -> {
                    _uiStateFlow.update { UiState(error = event.error) }
                }
                ResponseEvent.Loading -> {
                    _uiStateFlow.update { UiState(loading = true) }
                }
            }
        }
    }
data class UiState(
    val loading: Boolean = false,
    val list: List<PhotosModel> = emptyList(),
    val error: Throwable? = null
)
kotlin pagination android-jetpack-compose infinite-scroll lazycolumn
1个回答
0
投票

如果您像这样发送加载

UIState

_uiStateFlow.update { UiState(loading = true) }

如果不传递

list
属性的值,它将默认使用您在
emptyList
类中指定的
UIState

val list: List<PhotosModel> = emptyList()

因此,在加载时,

LazyVerticalStaggeredGrid
变为空,仅显示单个加载项。
要解决此问题,请在加载时将当前列表与
UIState
一起传递,如下所示:

_uiStateFlow.update { UiState(loading = true, list = uiStateFlow.value) }
© www.soinside.com 2019 - 2024. All rights reserved.