在我的应用程序中,我需要存储一个 map ,该 map 将特定用户与发送给当前用户的消息列表相关联.原始数据 struct 如下所示: val friendMessages = LinkedHashMap<User,ArrayList<Message>>().然而,使用Move to Compose时,我需要确保视图将重新组合 map 的任何大小更改以及 map 中的任何ArrayList更改的时间.我想做一些类似这样的事情,mutableStateMapOf<User, SnapshotStateList<Message>>(),然后用muableStateListOf()初始化每个列表,但我不知道状态更改是否会通过包含的映射进行.

推荐答案

是的,您可以彼此堆叠MuableState,并且读取State的作用域将重新组合,无论它是在哪种数据 struct 中,除非您将使用SnapshotStateMap丢失LinkedHashMap的排序,但您可以通过索引或排序参数进行排序.

你可以添加用户,为所选用户设置消息,或从 map 中删除用户,如下面的gif所示,重组将生效.

enter image description here

我做了一个样品来展示你的建议是有效的.

@Preview
@Composable
private fun TestNestedStructure() {
    val map = remember {
        mutableStateMapOf<User, SnapshotStateList<Message>>()
    }

    var user by remember {
        mutableStateOf<User?>(null)
    }

    var userName by remember {
        mutableStateOf("")
    }

    var message by remember {
        mutableStateOf("")
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(top = 20.dp)
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            OutlinedTextField(
                modifier = Modifier.weight(1f),
                value = userName,
                onValueChange = {
                    userName = it
                }
            )

            Button(onClick = {
                map[User(userName)] = mutableStateListOf()
            }) {
                Text(text = "Add User")
            }
        }

        Row(verticalAlignment = Alignment.CenterVertically) {
            OutlinedTextField(
                modifier = Modifier.weight(1f),
                value = message,
                onValueChange = {
                    message = it
                }
            )

            Button(onClick = {
                user?.let {
                    map[it]?.run {
                        add(Message(text = message))
                    }
                }
            }) {
                Text(text = "Add Message")
            }
        }

        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            contentPadding = PaddingValues(16.dp)
        ) {

            val users = map.keys.toList()

            items(
                items = users,
                key = { item ->
                    item.uuid
                }
            ) { currentUser: User ->
                Column(
                    modifier = Modifier
                        .shadow(2.dp)
                        .border(2.dp, getRandomColor())
                        .background(Color.White)
                        .fillMaxWidth()
                        .clickable {
                            user = currentUser
                        }
                        .padding(8.dp)
                ) {
                    Row {
                        Text(
                            modifier = Modifier.weight(1f),
                            text = currentUser.name
                        )
                        IconButton(onClick = {
                            map.remove(currentUser)
                        }) {
                            Icon(imageVector = Icons.Default.Remove, contentDescription = "remove")
                        }
                    }
                    map[currentUser]?.forEach { message ->
                        Text(
                            modifier = Modifier.padding(start = 10.dp),
                            text = message.text
                        )
                    }
                }
            }
        }
    }
}

数据类

data class Message(val text: String)

data class User(val name: String, val uuid: UUID = UUID.randomUUID())

还添加了边框,以查看每次重组时 colored颜色 随机变化的重组

fun getRandomColor() =  Color(
    red = Random.nextInt(256),
    green = Random.nextInt(256),
    blue = Random.nextInt(256),
    alpha = 255
)

Android相关问答推荐

如何使用Gradle风味在两个Kotlin导入(Google vs Amazon Java billing library)之间进行 Select ?

如何检测HitTest是否命中给定的网格对象?

从单元测试访问RES/RAW文件

如何阻止Gradle在编译时生成app-metadata.properties

Android:微调:在代码中设置ArrayAdapter不希望调用On ItemSelected,仅当用户单击微调时调用

设置文本 colored颜色 动画时如何减少重新组合?

如何在使用 PointerInput 修改器时添加点击时的波纹效果

Android v31 及更低版本中 ImageView 中的圆角

SQLite Kotlin 问题 - 没有数据库

发布 MAUI 应用程序时出现遇到重复程序集错误

延时kotlin中时分秒的使用方法

Android工作室未成立

如何在 Jetpack Compose 中设置行宽等于 TextField 的宽度?

调用时 listFiles() nullpointerexception

如何将房间数据库导出到 .CSV

EAS 构建失败,错误代码为 1,但 Expo Build 成功,我需要 EAS 构建来删除未使用的包,如 com.segment.analytics.android:analytics

现代Android中的后台处理

任何 IRCTC 的公共 API 来判断 PNR 状态和座位可用性?

如何获取 Android Preferences DataStore 的所有键

Android:如何获取具有纬度和经度的位置的图像