You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UUID作为LazyColumn项Key时无限加载,OID遇重复项崩溃求解决方案

解决LazyColumn重复帖子的唯一Key问题

问题根源

  • 直接用MongoDB的OID当Key:同一帖子重复出现时,Key重复触发LazyColumn的重复Key崩溃。
  • 用UUID.randomUUID()生成Key:每次重组都会生成全新Key,LazyColumn会将所有项视为新内容,不断销毁重建PostComposable,导致加载异常。

可行解决方案

方案1:使用itemsIndexed生成组合Key

通过itemsIndexed获取项的索引,将OID与索引拼接成唯一Key,既保留帖子标识,又区分重复项:

LazyColumn(
    verticalArrangement = Arrangement.spacedBy(10.dp),
    modifier = Modifier.fillMaxWidth(),
    state = lazyColState
) {
    itemsIndexed(items = viewModel.postsList.value, key = { index, postString ->
        val postDocument = Document.parse(postString)
        val postOID = (postDocument["_id"]!! as ObjectId).toString()
        // OID+索引生成唯一Key
        "$postOID_$index"
    }) { _, postString ->
        val postDocument = Document.parse(postString)
        PostComposable(
            owner = postDocument["owner"]!! as String,
            ownerOID = (postDocument["ownerOID"]!! as ObjectId).toString(),
            title = postDocument["title"]!! as String,
            datePosted = postDocument["postingDate"]!! as String,
            resource = postDocument["resource"]!! as String,
            numberLikes = postDocument["likes"]!! as Int,
            postOID = (postDocument["_id"]!! as ObjectId).toString(),
            navController = navController,
            viewModel = viewModel,
            snackbarHostState = snackbarHostState,
            isOwnedByUser = false,
            isOnHomePage = true,
            isSavedDefault = false
        )
    }
}

方案2:预处理数据源,添加本地唯一标识

在ViewModel层给每个帖子包装一个带本地唯一ID的对象,提前生成Key,简化LazyColumn的逻辑:

  1. 定义包装数据类:
data class PostWithLocalId(
    val localUniqueId: String,
    val postString: String
)
  1. ViewModel中处理帖子列表:
// 加载或更新帖子时生成本地唯一ID
fun updatePostsList(rawPosts: List<String>) {
    val processedPosts = rawPosts.mapIndexed { index, postStr ->
        val postDoc = Document.parse(postStr)
        val postOID = (postDoc["_id"]!! as ObjectId).toString()
        PostWithLocalId(
            localUniqueId = "$postOID_$index",
            postString = postStr
        )
    }
    postsList.value = processedPosts
}
  1. LazyColumn中使用包装后的列表:
LazyColumn(
    verticalArrangement = Arrangement.spacedBy(10.dp),
    modifier = Modifier.fillMaxWidth(),
    state = lazyColState
) {
    items(items = viewModel.postsList.value, key = { it.localUniqueId }) { postWithId ->
        val postDocument = Document.parse(postWithId.postString)
        PostComposable(
            // 保持原有参数传递
            owner = postDocument["owner"]!! as String,
            ownerOID = (postDocument["ownerOID"]!! as ObjectId).toString(),
            title = postDocument["title"]!! as String,
            datePosted = postDocument["postingDate"]!! as String,
            resource = postDocument["resource"]!! as String,
            numberLikes = postDocument["likes"]!! as Int,
            postOID = (postDocument["_id"]!! as ObjectId).toString(),
            navController = navController,
            viewModel = viewModel,
            snackbarHostState = snackbarHostState,
            isOwnedByUser = false,
            isOnHomePage = true,
            isSavedDefault = false
        )
    }
}

方案优势

两种方案都能保证Key的唯一性,同时不会触发LazyColumn的异常加载:

  • 方案1无需修改数据源,直接在LazyColumn中处理,适合快速修复。
  • 方案2将Key逻辑剥离到ViewModel,代码更清晰,便于后续维护。

内容的提问来源于stack exchange,提问作者Luca Strambeanu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:40:27