RecyclerView未初始化全部对象导致lateinit属性访问异常求助
解决方案
核心问题原因
RecyclerView采用按需创建ViewHolder的机制,未滚动到的Item不会触发ViewHolder初始化,导致你在ViewHolder中声明的lateinit属性从未被赋值,点击按钮访问时就会抛出kotlin.UninitializedPropertyAccessException。
推荐解决方案(从根源解决)
1. 替换lateinit为View Binding或可空类型
优先用View Binding:在ViewHolder中直接使用布局绑定类,彻底避免未初始化问题。示例代码:
class ItemPaletteViewHolder(private val binding: ItemPaletteBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(item: ItemPalette) { binding.colorItemLight.text = item.lightColorHex // 其他绑定逻辑 } }View Binding会在编译时生成绑定类,确保视图引用非空且已初始化,不存在未赋值的风险。
改用可空类型(临时过渡方案):如果暂时不想用View Binding,把
lateinit变量改成可空类型,访问时做null检查:class ItemPaletteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { var colorItemLight: TextView? = null init { colorItemLight = itemView.findViewById(R.id.color_item_light) } fun bind(item: ItemPalette) { colorItemLight?.text = item.lightColorHex } }点击按钮访问时,必须先判断
colorItemLight是否为null,避免直接调用导致崩溃。
2. 从数据源获取数据,而非ViewHolder视图
不要试图从ViewHolder中读取状态,应该直接操作你的ItemPalette数据源列表。比如点击cvAccept按钮时,遍历26个ItemPalette对象获取所需的颜色值,而不是去对应ViewHolder的colorItemLight中取文本。
示例:
cvAccept.setOnClickListener { val selectedColors = itemPaletteList.mapNotNull { item -> item.lightColor // 直接从数据源拿值,无需依赖ViewHolder } // 后续逻辑 }
这种方式完全不受ViewHolder是否创建的影响,是RecyclerView开发的标准实践。
应急方案(不推荐,影响性能)
如果必须强制初始化所有ViewHolder,可以通过以下方式让RecyclerView预加载所有Item:
// 假设使用LinearLayoutManager val layoutManager = rvPalette.layoutManager as LinearLayoutManager layoutManager.initialPrefetchItemCount = 26 // 预加载所有26个Item // 同时设置视图缓存大小 rvPalette.setItemViewCacheSize(26)
但此方案会让RecyclerView失去复用优势,增加内存占用,仅适合Item数量极少的场景。
内容的提问来源于stack exchange,提问作者Michael Karpiy
相关产品推荐
相关产品推荐

