我有一个组件,需要迭代并呈现一个Map<String, List<String>>.它们的键是"标题"和列表子项.

我想写我的代码如下:

@Composable
fun renderFullMap(groupedItems: Map<String, List<String>>) {
  LazyColumn {
    groupedItems.forEach { (header, things) ->
      renderSection(header, things)
    }
  }
}

@Composable
fun renderSection(header: String, things: List<String>) {
  stickyHeader { Text(header) }
  items(things) { thing -> Text(thing) }
}

(在实践中,实际数据和renderSection都比较复杂,但它们可以归结为这个基本概念.)

这不管用.它告诉我:

@可组合调用只能在@Composable函数的上下文中进行

如果我使用items在 map 键上迭代,我会得到一个不同的错误:

@Composable
fun renderFullMap(groupedItems: Map<String, List<String>>) {
  LazyColumn {
    items(groupedItems.keys.toList()) { header ->
      renderSection(header, groupedItems[header])
    }
  }
}

在这个版本中,stickyHeaderitemsrenderSection中是未定义的.

我试过的最后一件事是用LazyListScope.作为renderSection的前缀:

@Composable
fun LazyListScope.renderSection(header: String, things: List<String>) {
  stickyHeader { Text(header) }
  items(things) { thing -> Text(thing) }
}

这只是暗中捅了一刀.如果我在forEach中调用它,它会告诉我,它给出了关于只能从其他可编程组件调用的可编程组件的第一个错误.如果我从items()以内称之为:

"有趣的懒汉.".renderSection(header:String,things:List):在此上下文中,隐式接收方无法调用Unit.如有必要,使用显式

我不会假装知道那是什么意思.

我该怎么做?我怀疑我不知何故需要将LazyListScope扩展到renderSection个,但不清楚如何扩展.

编辑:我有点让它工作了,但我的列表项在滚动时成倍增加.此代码编译:

@Composable
fun renderFullMap(groupedItems: Map<String, List<String>>) {
  LazyColumn {
    val scope = this
    items(groupedItems.keys.toList()) { header ->
      scope.renderSection(header, groupedItems[header])
    }
  }
}

@Composable
fun LazyListScope.renderSection(header: String, things: List<String>) {
  stickyHeader { Text(header) }
  items(things) { thing -> Text(thing) }
}

然而,我不知道为什么 list 的内容不正常.

推荐答案

您的第一种方法接近正确的方法,您需要从renderSection中删除@Composable,并添加LazyListScope上下文:

@Composable
fun renderFullMap(groupedItems: Map<String, List<String>>) {
  LazyColumn {
    groupedItems.forEach { (header, things) ->
      renderSection(header, things)
    }
  }
}

fun LazyListScope.renderSection(header: String, things: List<String>) {
  stickyHeader { Text(header) }
  items(things) { thing -> Text(thing) }
}

Kotlin相关问答推荐

这些Kotlin函数等效吗?

Kotlin—从列表中枚举属性计算不同值的数量

在intellij中使用kotlin符号和floordiv

某些公共函数显然不能在类实例上访问;Klaxon示例

Groovy Gradle文件的Kotlin类似功能

在Kotlin项目中使用Free Fair AspectJ插件(使用Gradle)

合并状态流

Kotlin 说不需要强制转换,但删除后会出现新警告

Kotlin 复制列表中的项目以创建具有相同数据的不同对象的新列表

Ktor 在 Heroku 上的 CORS 问题,但在本地没有

TzdbZoneRulesProvider 在 java.time 中不工作

如何处理基于枚举提前返回的 forEach 循环,Kotlin 中的一条路径除外

你怎么知道什么时候需要 yield()?

多次运行espresso测试

Dagger 2 ContributesAndroidInjector 为模块提供活动

interface扩展

Mockito 的 argThat 在 Kotlin 中返回 null

从片段(fragment)中的点击事件启动协同程序

如果kotlin已经有了getter和setter,为什么在数据类中有componentN函数?

Kotlin 错误:public function exposes its 'public/*package*/' return type argument