A very very simple example (implementation(platform("androidx.compose:compose-bom:2023.08.00"))):
package com.study.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.study.myapplication.ui.theme.MyApplicationTheme
data class Id(val level: Int, val index: Int)
class Man(val id: Id, val name: String)
val men = listOf(
Man(Id(1, 1), "Amy"),
Man(Id(1, 2), "Bob")
)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting(men)
}
}
}
}
}
@Composable
fun Greeting(men: List<Man>, modifier: Modifier = Modifier) {
LazyColumn (modifier = modifier) {
items(men, key = { it.id.index }) { // <- render problem
//items(men, key = { it.id }) { // <- okay
Text(it.name)
}
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyApplicationTheme {
Greeting(men)
}
}
Refer to the comments in the code: If I use man.Id.index as key, it renders ok. If I use man.Id as key, it prompts render problem.
In a physic device, I found the real reason:
java.lang.IllegalArgumentException: Type of the key Id(level=1, index=1) is not supported. On Android you can only use types which can be stored inside the Bundle.
Why?
When you use
it.id.indexas the key, you're essentially using anIntvalue, which is a primitive type that can be easily stored in aBundle. But, when you useit.id, you're trying to use a customdata classid, which cannot be directly stored in aBundlebecause it's not a primitive type nor a type that implementsParcelable.So If needed, you can utilize
Parcelable.do not forget add
kotlin-parcelizeplugin to build.gradle