Jetpack Compose LazyRow中items函数匹配异常及导入生效原因问询
问题描述
我在跟着Jetpack Compose的LazyRow示例开发时发现,创建LazyRow对象时必须添加导入语句import androidx.compose.foundation.lazy.items,否则LazyRow内部的items函数会抛出错误:
Type mismatch: inferred type is List<DrawableStringPair> but Int was expected
我猜测编译器匹配到了其他重载函数,但这两个items函数都定义在同一个文件LazyDsl.kt里,想知道为什么这个导入语句能指定使用接受List<T>参数的items函数:
inline fun <T> LazyListScope.items( items: List<T>, noinline key: ((item: T) -> Any)? = null, noinline contentType: (item: T) -> Any? = { null }, crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit ) = items(
而非接受Int参数的items函数:
fun items( count: Int, key: ((index: Int) -> Any)? = null, contentType: (index: Int) -> Any? = { null }, itemContent: @Composable LazyItemScope.(index: Int) -> Unit ) { error("The method is not implemented") }
原因分析
这是Kotlin作用域解析与导入优先级导致的:
- 接受
Int参数的items是LazyListScope接口的成员函数,当你在LazyRow的lambda(属于LazyListScope作用域)中调用items时,编译器会优先匹配这个作用域内的成员函数。 - 接受
List<T>参数的items是顶层扩展函数,它不属于LazyListScope的成员,默认不会被自动纳入当前作用域。只有显式导入androidx.compose.foundation.lazy.items后,编译器才能识别到这个扩展函数,并且因为它的参数类型和你传入的List<DrawableStringPair>完全匹配,会优先选择这个重载版本。
即便两个函数在同一个文件中,成员函数的优先级高于未导入的顶层扩展函数,所以不导入时编译器只会找到需要Int参数的版本,从而抛出类型不匹配错误。
相关代码示例
数据定义
private val alignYourBodyData = listOf( R.drawable.ab1_inversions to R.string.ab1_inversions, R.drawable.ab2_quick_yoga to R.string.ab2_quick_yoga, R.drawable.ab3_stretching to R.string.ab3_stretching, R.drawable.ab4_tabata to R.string.ab4_tabata, R.drawable.ab5_hiit to R.string.ab5_hiit, R.drawable.ab6_pre_natal_yoga to R.string.ab6_pre_natal_yoga ).map { DrawableStringPair(it.first, it.second) }
出现问题的函数
@Composable fun AlignYourBodyRow( modifier: Modifier = Modifier ) { LazyRow( horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = modifier ) { // 未导入List版本的items时,编译器匹配到Int参数的重载,报错 items(alignYourBodyData) { item -> AlignYourBodyElement(item.drawable, item.text) } } }
修复方式:添加导入语句
在文件顶部添加:
import androidx.compose.foundation.lazy.items
可组合函数
@Composable fun AlignYourBodyElement( @DrawableRes drawable: Int, @StringRes text: Int, modifier: Modifier = Modifier ) { Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally ) { Image( painter = painterResource(drawable), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier .size(88.dp) .clip(CircleShape) ) Text( text = stringResource(text), style = MaterialTheme.typography.h3, modifier = Modifier.paddingFromBaseline( top = 24.dp, bottom = 8.dp ) ) } }
内容的提问来源于stack exchange,提问作者tim p
相关产品推荐
相关产品推荐

