Kotlin Extension Functions suddenly require api level 24
Asked Answered
D

4

41

I just noticed this lint error:

Call requires API Level 24 (current min is 19) java.util.map#foreach

when I use the extension function forEach on a MutableMap in Kotlin. This didn't happen when I wrote the line, but its there now. And I'm not seeing this error on my other machine.

Dozen answered 25/6, 2017 at 23:21 Comment(5)
Try invalidate cache and run gradle clean since your other machine isn't getting that error. Also check Naetmul's anwser below.Brassard
Whilst Naetmul's answer seems to be the cause of your issue, I'm currently seeing a lot of these warnings for no reason in AS3.0 anyway, even in things like Bundle#putBoolean. Linting seems a bit broken currently.Rum
In case you recently pass by here after migrating to Kotlin 1.5.0, there is a Lint bug in AGP 4.1, causing a similar issues. Please refer to issuetracker.google.com/issues/185418482 for details. TL;DR you need to update to AGP 4.2.0 firstClomb
Not resolved to this date even with the latest version of AGP. Thanks a lot Konsumierer for the issuetracker link, will follow this closely.Arguello
This issue reappears in Kotlin 1.9.x, for people coming here due to that: the answers below still workStephaniastephanie
C
85

What you are using is not kotlin.collections.MutableMap.forEach.

What you are using seems to be Map.forEach in Java 8.

Refer to this article: http://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/

This seems to be a common mistake.

Java 8 is well-supported from Android API level 24.

For short, do not use forEach like map.forEach { t, u -> Log.i("tag", t + u) } (this is using Java 8 API, which does not work for Android API level <= 23).
Use it like map.forEach { (t, u) -> Log.i("tag", t + u) } (this is using Kotlin API).
(Not two parameters. Just one parameter that is a pair.)

Cropeared answered 26/6, 2017 at 1:56 Comment(9)
this solved it for me. The same thing is happening for replace() on MutableMap, so im guessing this is the same causeMilton
double accepted answer. this allows me to use forEach on kotlin.Settler
The file is entirely written in Kotlin, and it still gives this error. There's no way to be using Java 8 from Kotlin.Ascend
@Ascend Typically you're using Kotlin with some Java libraries, so the Java version of those libraries may matter. The two arg version of j.u.Map.forEach is from Java 8 onwards, i.e., Android API 24 onwards.Unpaid
@Cropeared what is the relation between java language features and android api levels?Crossroad
@SouravKannanthaB Android API Level <= 23: Java 7, Android API Level >= 24: Subset of Java 8, developer.android.com/studio/write/java8-support.html It seems that Google does not try to include Java 9 language features to Android. Just use Kotlin instead.Cropeared
BTW, I found the same issue reappeared after the kotlin 1.5.x upgrade. It was a problem that is already fixed in 4.2: issuetracker.google.com/issues/185418482Frydman
I am using the single argument version and this problem just appeared for me. ref event.attributes?.forEach { (key, value) -> if (key != null && value != null) { put(key, value) } }Dissatisfied
I have like 30 places where I get this error and can't manage to make it work with this solution. I have to use import kotlin.collections.forEach as kForEach and then use kForEach instead of forEachAnabelanabella
A
11

This also happens in a list even tho I'm using I need to use:

list.iterator().forEach {}

the key is use iterator() before forEach.

Absolution answered 28/5, 2021 at 11:25 Comment(1)
This solved it for me. I am using the single argument version as mentioned in another answer (ref. event.attributes?.forEach { (key, value) -> if (key != null && value != null) { put(key, value) } }).Dissatisfied
C
2

Ran into this because the map a dependency provided was a Java 8 map, so the forEach was linted as the Java 8 version, no matter how I grouped my parameters in the lambda signature (one, two -> vs (one, two) ->). Best solution I could find was using an explicit import with an alias (import kotlin.collections.forEach as kForEach). The alias keeps optimize imports from removing the explicit import.

Cecil answered 23/8, 2021 at 18:46 Comment(0)
S
-3

Map.forEach is supported in Java 8 and its support in Android started from API 24

Syntactics answered 26/6, 2017 at 5:38 Comment(1)
This is for KotlinAscend

© 2022 - 2024 — McMap. All rights reserved.