使用 LazyListScope 嵌套可组合项

dav*_*off 4 kotlin android-jetpack-compose

我有一个可组合项,需要迭代并渲染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) }
}
Run Code Online (Sandbox Code Playgroud)

(实际上,实际数据 和renderSection都更复杂,但它们都归结为这个基本思想。)

这是行不通的。它告诉我:

@Composable 调用只能在 @Composable 函数的上下文中发生

如果我用来items迭代我的地图键,我会得到一个不同的错误:

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

在此版本中,stickyHeaderitemsrenderSection.

我尝试的最后一件事 -renderSection前缀LazyListScope.

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

这只是暗中刺伤而已。如果我在 a 中调用它,forEach它会告诉我它会给出第一个关于只能从其他可组合项调用的可组合项的错误。如果我从内部调用它items()

'fun LazyListScope.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) }
}
Run Code Online (Sandbox Code Playgroud)

然而,我不知道为什么列表的内容不正常。

Phi*_*hov 12

您的第一种方法接近正确的方法,您需要删除@ComposablerenderSection添加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) }
}
Run Code Online (Sandbox Code Playgroud)