7

I am using Kotlin's MutableMap in my Android project. And trying to do some action per item. So here is my code.

private val uris: MutableMap<String, Uri> = mutableMapOf()
// ... Fill the items here ...
uris.forEach {
    val ref = FirebaseFirestore.getInstanse().reference
    uploadFile(ref, it.value)
}

Everything just works fine at runtime, but my CI build fails with below lint error:

MyActivity.kt:142: Error: Call requires API level 24 (current min is 16): java.util.Map#forEach [NewApi]
              uris.forEach {
                   ~~~~~~~

I know we can't use JDK-8's Map for Android projects until the min sdk is 24. But why lint is considering it as JDK-8's Map?

For further information I tried getting the Java code from Kotlin Bytecode option in AS and found that forEach is replaced with while loop and iterator as expected.

So what could be reason and how to solve this? Any lead will be appreciated.

Chandra Sekhar
  • 18,914
  • 16
  • 84
  • 125
  • Do you have the Kotlin standard library in your dependencies? – zsmb13 Jan 25 '18 at 08:59
  • 1
    In the code sample map's name is `uris`, while in the error message it's `shopIcons`. Are you sure you're looking in the right place? – Alex Filatov Jan 25 '18 at 09:08
  • 3
    Possible duplicate of [Kotlin Extension Functions suddenly require api level 24](https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24) – MJakhongir Jan 25 '18 at 09:33
  • @AlexFilatov, thats my mistake. It was a copy paste problem. Fixed it now. – Chandra Sekhar Jan 25 '18 at 10:39
  • Can it be a error in the Link check? – voddan Jan 25 '18 at 10:41
  • Lint __should__ resolve the method used the same way as the IDE's editor and the compiler does though. @ChandraSekhar if you navigate to the declaration of the `forEach` you're using, does it go to the Kotlin one as it should? – zsmb13 Jan 25 '18 at 10:50
  • 1
    @zsmb13, yes it goes to kotlin one. Not to the Java one. – Chandra Sekhar Jan 25 '18 at 10:52

3 Answers3

11

There are two overloaded foreachs on Map:

Kotlin one:

uris.forEach { (key, value) -> // Do some Action }

Java8 one:

uris.forEach { key, value -> // Do some Action }

Confusing, isn't it?

voddan
  • 31,956
  • 8
  • 77
  • 87
2

I think this is an import problem. Maybe you have used JDK 8's Map.forEach.

You have to use kotlin.collections.MutableMap.forEach

You can also check this blog:

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

Avijit Karmakar
  • 8,890
  • 6
  • 44
  • 59
0

Are you sure that you use forEach from Kotlin? Because there are two forEach, one from Kotlin with Map.Entry as an argument and one from Java with two arguments: key and value. Please, show full version of your code. If you use forEach without arguments, it means that you use Kotlin one (you have it implicit argument).

If you use Kotlin forEach and still have this warning you should report this issue to Android Issue Tracker

gildor
  • 1,789
  • 14
  • 19
  • @ChandraSekhar You use Kotlin version of forEach, so it's lint bug. Suppress this warning in Lint and report an issue to Android tracker – gildor Jan 25 '18 at 08:44