簡體   English   中英

Jetpack Compose:LazyColumn 不更新項目

[英]Jetpack Compose: LazyColumn does not update items

我有一個來自 viewModel 的lazyColumn 接收列表來創建項目:

@Composable
fun HomeList(
    modifier: Modifier = Modifier,
    dataList: List<Data>,
    listState: LazyListState = rememberLazyListState(),
    onClickItem: (Data) -> Unit,
    onLongPressItem: (Data) -> Unit
) {
    LazyColumn(
        modifier = modifier,
        state = listState
    ) {
        items(dataList) { data ->
            Log.d(TAG, "HomeList: add data $data")
            HomeListItem(
                data = data,
                onClick = onClickItem,
                onLongPressed = onLongPressItem
            )
        }
    }
}

該列表包裝在 viewModel 中的 stateFlow 中,並在 Composable 中收集為 state:

    // viewModel
    ...
    private val _uiState = MutableStateFlow(
        HomeUiState(
            ...
            homeList = listOf()
        )
    )
    val uiState = _uiState as StateFlow<HomeUiState>
    ...
// HomeScreen
val uiState by viewModel.uiState.collectAsState()
...
HomeList(
    modifier = Modifier
        .padding(it)
        .navigationBarsPadding(),
    dataList = uiState.homeList,
    listState = listState,
    onClickItem = { data ->
        ...
    },
    onLongPressItem = {
        ...
    }
)

ViewModel 將從 Room 數據庫中加載數據並根據當前屏幕類型過濾不感興趣的數據:

data class HomeUiState(
    val homeType: HomeType,
    val homeList: List<Data>
)

enum class HomeType {
    CREATED,
    VIEWED,
    STARRED,
    ARCHIVED
}
...
viewModelScope.launch(Dispatchers.IO) {
            repository.getAllDataFlow().collect { newList ->
                Log.d(TAG, "collect new list: $newList")
                when (_uiState.value.homeType) {
                    HomeType.CREATED -> _uiState.update { it.copy(homeList = homeList.filter { data -> data.status == MarkdownData.STATUS_INTERNAL }) }
                    HomeType.VIEWED -> _uiState.update { it.copy(homeList = homeList.filter { data -> data.status == MarkdownData.STATUS_EXTERNAL }) }
                    HomeType.STARRED -> _uiState.update { it.copy(homeList = homeList.filter { data -> data.isStarred == MarkdownData.IS_STARRED }) }
                    HomeType.ARCHIVED -> _uiState.update { it.copy(homeList = homeList.filter { data -> data.status == MarkdownData.STATUS_ARCHIVED }) }
                }
            }
        }

這是我的問題:每次我在 Room 數據庫中刪除一個數據 object 時,流程都會發出新值(刪除后的數據列表),該值被收集並用於更新 Ui State 以進行重組。 日志和實驗表明確實如此:viewModel 收集新列表,然后lazyColumn 觀察新列表並使用items語法創建可組合項目,並從 UI 中明顯刪除已刪除的項目。

然而,盡管使用新的數據列表進行了重組,但每個可組合項的數據 object 仍然是舊的,並且沒有按預期更新。 例如,如果我有 a、b、c、d 的列表。 刪除a后,列表應該是b,c,d。 UI中顯示的列表確實代表b,c,d,但它們的實際值對應舊的a,b,c,這阻礙了進一步的操作。 但是如果我刷新屏幕(重新啟動應用程序或導航到其他屏幕然后彈出),一切都會恢復正常。

我想知道我是否錯過了任何導致lazyColumn 項目更新UI 但不更新每個項目的實際數據的東西。 謝謝!

我認為需要在下面的LazyColumn項目中添加鍵,這將有助於將項目識別為一種獨特的方式。

LazyColumn(
        modifier = modifier,
        state = listState
    ) {
        items(dataList,
            key = { listItem ->
                listItem.id // or any other unique
            })
        { data ->
            Log.d(TAG, "HomeList: add data $data")
            HomeListItem(
                data = data,
                onClick = onClickItem,
                onLongPressed = onLongPressItem
            )
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM