一个非常非常简单的例子(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)
}
}
参考代码中的注释: 如果我使用 man.Id.index 作为键,它呈现正常。 如果我使用 man.Id 作为 key,会提示渲染问题。
在物理设备中,我找到了真正的原因:
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.
为什么?
当您使用
it.id.index
作为键时,您本质上是在使用 Int
值,它是一种可以轻松存储在 Bundle
中的原始类型。但是,当您使用 it.id
时,您正在尝试使用自定义 data class
id
,它不能直接存储在 Bundle
中,因为它不是原始类型,也不是实现 Parcelable
的类型。
因此,如果需要,您可以利用
Parcelable
。
@Parcelize
data class Id(val level: Int, val index: Int): Parcelable
不要忘记添加
kotlin-parcelize
插件到 build.gradle
plugins {
id("kotlin-parcelize")
}