Kotlin扩展函数突然需要API级别24

40

我刚刚注意到这个lint错误:

调用需要API Level 24 (当前最小值为19) java.util.map#foreach

当我在Kotlin的MutableMap上使用扩展函数forEach时出现了这个问题。 我写这行代码时没有出现这个错误,但现在它出现了。 而且我在我的另一台机器上没有看到这个错误。


尝试清除缓存并运行 gradle clean,因为您的另一台机器没有出现该错误。还要检查下面Naetmul的答案。 - glee8e
虽然Naetmul的回答似乎是您问题的原因,但我目前在AS3.0中看到了很多无缘无故的警告,甚至在像Bundle#putBoolean这样的东西中也是如此。目前Linter似乎有点出了问题。 - ditn
13
如果您最近迁移到Kotlin 1.5.0并经过此处时,AGP 4.1中存在一个Lint bug,导致出现类似问题。请参考https://issuetracker.google.com/issues/185418482了解详情。 简而言之,您需要先升级到AGP 4.2.0。 - Konsumierer
即使使用最新版本的AGP,问题仍未得到解决。非常感谢Konsumierer提供的issuetracker链接,我会密切关注此事。 - Charly Lafon
这个问题在Kotlin 1.9.x中重新出现,对于因此而来到这里的人们:下面的答案仍然适用 - avalancha
4个回答

84
你所使用的不是 kotlin.collections.MutableMap.forEach
你所使用的似乎是 Java 8 中的 Map.forEach
请参考这篇文章:http://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/ 这是一个常见的错误。
Android API 等级 24 及以上版本支持 Java 8。
简而言之,不要像这样使用 forEachmap.forEach { t, u -> Log.i("tag", t + u) }(这是使用 Java 8 API,不适用于 Android API 等级 <= 23)。 应该像这样使用:map.forEach { (t, u) -> Log.i("tag", t + u) }(这是使用 Kotlin API)。 (不是两个参数。只有一个成对出现的参数。)

2
这对我解决了问题。在MutableMap上使用replace()也出现了相同的情况,所以我猜这是同样的原因。 - Sebastian Rüttger
1
双重接受答案。这使我能够在Kotlin上使用forEach。 - mochadwi
2
通常您会使用Kotlin与一些Java库,因此这些库的Java版本可能很重要。 j.u.Map.forEach的两个参数版本是从Java 8开始的,即Android API 24开始。 - Ricky Clarkson
@SouravKannanthaB Android API Level <= 23: Java 7,Android API Level >= 24: Java 8 的子集,https://developer.android.com/studio/write/java8-support.html 看起来 Google 并没有尝试将 Java 9 语言特性包含到 Android 中。最好使用 Kotlin 替代。 - Naetmul
我有大约30个地方出现了这个错误,但是用这个解决方案还是无法解决。我必须使用“import kotlin.collections.forEach as kForEach”,然后使用kForEach代替forEach。 - Damia Fuentes
显示剩余4条评论

11
即使我使用,列表中也会发生这种情况:
list.iterator().forEach {}

关键在于在forEach之前使用iterator()

这对我解决了问题。我正在使用单参数版本,如另一个答案中所提到的(参考 event.attributes?.forEach { (key, value) -> if (key != null && value != null) { put(key, value) } })。 - Bill Mote

2
因为依赖提供的地图是Java 8地图,所以无论我如何在lambda签名中分组参数(one,two -> vs (one,two) ->),forEach都会被视为Java 8版本。我找到的最佳解决方案是使用带有别名的显式导入(import kotlin.collections.forEach as kForEach)。别名可以防止优化导入删除显式导入。

-3

Map.forEach在Java 8中得到支持,而它在Android上的支持始于API 24


这是针对 Kotlin 的。 - IgorGanapolsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接