Kotlin从Synthetics转ViewBinding时Adapter的binding未初始化报错如何解决
错误根因
你当前的代码存在两个核心问题导致报错:
- 你将
MessageItemBinding声明为Adapter的全局属性,违背了RecyclerView的复用逻辑:每个列表项对应独立的Binding实例,全局唯一的Binding实例既无法匹配多个列表项的渲染需求,也没有在任何位置执行初始化操作,所以抛出lateinit未初始化的异常。 - 代码中同时混用
findViewById和ViewBinding,没有完全发挥ViewBinding的优势。
修复方案
将Binding实例放到ViewHolder中托管,在创建ViewHolder时完成Binding初始化,修改后的完整代码如下:
class MessagingAdapter: RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() { var messagesList = mutableListOf<Message>() // 将binding作为ViewHolder的成员变量,每个ViewHolder对应一个独立的binding实例 inner class MessageViewHolder(val binding: MessageItemBinding) : RecyclerView.ViewHolder(binding.root) { init { itemView.setOnClickListener { //Remove message on the item clicked messagesList.removeAt(adapterPosition) notifyItemRemoved(adapterPosition) } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder { // 直接通过ViewBinding的inflate方法创建实例,完成初始化 val binding = MessageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return MessageViewHolder(binding) } override fun getItemCount(): Int = messagesList.size @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: MessageViewHolder, position: Int) { val currentMessage = messagesList[position] val binding = holder.binding when (currentMessage.id) { SEND_ID -> { binding.tvMessage.apply { text = currentMessage.message visibility = View.VISIBLE } binding.tvBotMessage.visibility = View.GONE } RECEIVE_ID -> { binding.tvBotMessage.apply { text = currentMessage.message visibility = View.VISIBLE } binding.tvMessage.visibility = View.GONE } } } fun insertMessage(message: Message) { this.messagesList.add(message) notifyItemInserted(messagesList.size) } }
修改说明
- 移除了Adapter全局的
lateinit var binding声明,改为将Binding实例作为ViewHolder的成员变量,匹配RecyclerView的复用逻辑 - 在
onCreateViewHolder中直接通过MessageItemBinding.inflate完成Binding实例的创建和初始化,不需要单独inflate布局 - 移除了所有
findViewById调用,直接通过ViewHolder持有的Binding实例访问布局控件,避免空指针风险同时提升性能
内容的提问来源于stack exchange,提问作者Jeffrey Kurdt Dreo
相关产品推荐
相关产品推荐

