【问题标题】:Android Compose LazyColumn IllegalArgumentException: Key was already usedAndroid Compose LazyColumn IllegalArgumentException:密钥已被使用
【发布时间】:2021-12-18 22:31:47
【问题描述】:

我不断收到 IllegalArgumentException: Key was already used。如果您使用的是 LazyColumn/Row,请确保为每个项目提供唯一的键。

我确信我的钥匙是独一无二的。这是我的示例代码:

@Composable
fun UiComponent() {
    LazyColumn(
                verticalArrangement = Arrangement.spacedBy(12.dp),
                state = scrollState,
                reverseLayout = true
            ) {
                items(
                    items = viewmodel.messages,
                    key = { item -> item.hashcode() },
                    itemContent = { item: Entity ->
                        if (item.isDeleted) {
                            //show deleted ui
                        } else {
                            //show messages
                        }
                    })
            }
        }
}

ViewModel {

    init { 
       observeDataFromDB()
    }

    private val _messages: MutableList<Entity> = mutableStateListOf()
    val messages: List<Entity> = _messages


    fun observeDataFromDB() {
        viewModelScope.launch {
            repo.getData().collect {
                _messages.apply {
                    addNewItem(it)
                }
            }
        }
    }

}


//extensions
fun MutableList<Entity>.addNewItem(entity: Entity) {
    if (this.size >= MAX_SIZE) {
        removeLast()
    }
    Log("existing ${this.toList().map { "${it.hashCode()}" }}")
    Log("adding new ${entity.hashCode()}")
    this.add(0, entity)
}

//id is unique
data class Entity(id:String, isDeleted: Boolean, message: String)

我也尝试从我的 Viewmodel(StateFlow&lt;List&lt;Entity&gt;) 中提供一个 observable,但我得到了同样的错误。还尝试将id 设置为键。

通常在快速添加项目时遇到此问题。例如,用户在短时间内发送多条垃圾邮件。

【问题讨论】:

  • 请添加数据类Entity代码。
  • 究竟什么时候发生错误?当您启动应用程序时,或者当您实际滚动列时?
  • 当一个项目被添加到惰性列时
  • 即使 ID 是唯一的,您仍然可能有重复的数据,这使得 LazyColum “认为” ID 不是唯一的。所以检查重复并在那里解决问题。导致问题的快速消息表明它可能是这种情况。

标签: android-jetpack-compose


【解决方案1】:

如果您的任何消息相同,您最终会得到相同的哈希码值,这将产生错误。为避免这种情况,如果您的消息没有 id,请使用 itemsIndexed 而不是仅使用 items 并将索引指定为键:

@Composable
fun UiComponent() {
    LazyColumn(
                verticalArrangement = Arrangement.spacedBy(12.dp),
                state = scrollState,
                reverseLayout = true
            ) {
                items(
                    items = viewmodel.messages,
                    key = { item -> item.id },
                    itemContent = { item: Entity ->
                        if (item.isDeleted) {
                            //show deleted ui
                        } else {
                            //show messages
                        }
                    })
            }
        }
}

【讨论】:

  • 但是 id 永远是唯一的。 data class Entity(val id: String, isDeleted: Boolean, val message: String)。另外,如果我使用索引,如果Entity 中的isDeleted 发生变化,LazyColumn 中的任何行都会被重新组合吗?
  • 您没有使用 id。您正在将密钥设置为 item.hashcode()。我更新了我的代码并将 item.hashcode 替换为 item.id。
  • 还是一样的错误:(
  • 在调用 LazyColumn 之前将所有项目的 id 打印到 Log 并检查它们是否都是唯一的。我很确定您的列表中有重复的项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 2022-07-29
  • 2023-03-05
  • 2022-08-22
  • 2016-06-06
  • 1970-01-01
  • 2021-06-01
相关资源
最近更新 更多