I keep getting IllegalArgumentException: Key was already used. If you are using LazyColumn/Row please make sure you provide a unique key for each item.
I am sure my keys are unique. Here is my sample code:
@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)
I have also tried providing an observable from my Viewmodel(StateFlow<List<Entity>) but I get the same error. Also tried setting id as the key.
Mostly encountering this issue when items are rapidly added. For example user spamming multiple messages in a short time.
If any of your messages are identical, you'll end up with the same hashcode value and this will generate the error. To avoid this, if your messages don't have an id, use itemsIndexed instead of just items and assign the index as the key:
@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
}
})
}
}
}
If anyone is facing similar issue:
For me it got resolved after removing mutableStateListOf and using a simple list and observing this list in composable as state.
Basically StateFlow<List< Entity>> and in compose viewmodel.message.collectAsState(). Finally passing this list to the lazyColumn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With