Android minSdk22下调用List.forEach报NewApi错误如何解决
该NewApi报错的核心原因是代码编译时匹配到了Java 8新增的原生接口默认方法java.lang.Iterable#forEach,这个方法从Android API 24才开始内置支持,项目配置的minSdk为22,低版本系统不存在该方法,因此Lint检查直接阻断了构建。
正常情况下Kotlin集合调用forEach应该优先匹配Kotlin标准库提供的、兼容全Android版本的扩展函数,出现这个匹配错误是Kotlin 1.6.10和4.2.2版本Android Gradle插件的兼容问题导致的方法解析优先级异常。
方案1:强制匹配Kotlin标准库forEach(零配置,即时生效)
不需要修改任何项目依赖或编译配置,仅调整代码写法让编译器正确识别到Kotlin扩展函数即可,两种写法任选其一:
写法1:显式声明Lambda参数,避免Lint误判private val recipes: List<Recipe>, ... recipes.forEach { recipe -> recyclerItems.add(RecipeBinder(recipe, imageLoader, onRecipeClick)) }写法2:显式指定调用Kotlin集合扩展,彻底绕开Java原生方法匹配
recipes.forEach kotlin.collections@{ recyclerItems.add(RecipeBinder(it, imageLoader, onRecipeClick)) }方案2:开启核心库脱糖(长期维护推荐)
如果项目中需要用到较多Java 8新增的原生API,可以直接开启核心库脱糖支持,配置完成后可以在minSdk 21及以上版本正常使用所有Java 8原生API,不会再触发这类NewApi报错。
配置步骤:- 在对应模块的
build.gradle中开启Java 8编译配置:
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } }- 在同文件中开启脱糖开关并添加对应依赖:
android { compileOptions { // 保留上述sourceCompatibility/targetCompatibility配置 coreLibraryDesugaringEnabled true } } dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2' }配置完成后同步项目即可。
- 在对应模块的
方案3:替换为基础for循环(无任何兼容问题)
直接将forEach调用替换为Kotlin基础for-in循环,不存在任何API版本依赖,兼容所有Android版本:private val recipes: List<Recipe>, ... for (recipe in recipes) { recyclerItems.add(RecipeBinder(recipe, imageLoader, onRecipeClick)) }
避坑提示:不要直接使用
@SuppressLint("NewApi")注解忽略该报错,忽略后在API 22及以下版本设备运行到这段代码时,会直接抛出NoSuchMethodError导致崩溃。
内容的提问来源于stack exchange,提问作者Vladimir Fisher

