[英]lateinit property binding has not been initialized
I know that there are similar questions to this, but I just cant find something that is similar, I've been studying new things to learn, and while converting kotlin synthetics to viewvbinding
mode, I've encountered this error我知道有类似的问题,但我只是找不到类似的东西,我一直在研究新的东西来学习,在将 kotlin 合成转换为viewvbinding
模式时,我遇到了这个错误
kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized at com.codepalace.chatbot.ui.MessagingAdapter.onBindViewHolder(MessagingAdapter.kt:60) at com.codepalace.chatbot.ui.MessagingAdapter.onBindViewHolder(MessagingAdapter.kt:17)
It says that I have to initialize the binding, but I dont know where to put it.它说我必须初始化绑定,但我不知道把它放在哪里。
This is the code.这是代码。
class MessagingAdapter: RecyclerView.Adapter<MessagingAdapter.MessageViewHolder>() {
var messagesList = mutableListOf<Message>()
private lateinit var binding: MessageItemBinding
inner class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
//Remove message on the item clicked
messagesList.removeAt(adapterPosition)
notifyItemRemoved(adapterPosition)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
return MessageViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.message_item, parent, false)
)
}
override fun getItemCount(): Int {
return messagesList.size
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
val currentMessage = messagesList[position]
when (currentMessage.id) {
SEND_ID -> {
holder.itemView.findViewById<View>(R.id.tv_message).apply {
binding.tvMessage.text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.findViewById<View>(R.id.tv_bot_message).visibility = View.GONE
}
RECEIVE_ID -> {
holder.itemView.findViewById<View>(R.id.tv_bot_message).apply {
binding.tvBotMessage.text = currentMessage.message
visibility = View.VISIBLE
}
holder.itemView.findViewById<View>(R.id.tv_message).visibility = View.GONE
}
}
}
fun insertMessage(message: Message) {
this.messagesList.add(message)
notifyItemInserted(messagesList.size)
}
private lateinit var binding: MessageItemBinding
You didn't initialize the binding
object, as you defined it as lateinit, then you should define it.您没有初始化binding
object,因为您将其定义为lateinit,那么您应该定义它。
This is typically in onCreateViewHolder
这通常在onCreateViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TrackedActivityHolder {
val inflater = LayoutInflater.from(parent.context)
binding = DataBindingUtil.inflate<MessageItemBinding>(inflater, R.layout.message_item, parent, false)
return MessageViewHolder(
binding
)
}
UPDATE更新
You need to accept MessageItemBinding
type instead of View
in the MessageViewHolder
constructor, and use itemView.root
to get the root view of the list item.您需要在MessageViewHolder
构造函数中接受MessageItemBinding
类型而不是View
,并使用itemView.root
获取列表项的根视图。
inner class MessageViewHolder(itemView: MessageItemBinding) : RecyclerView.ViewHolder(itemView.root) {
init {
itemView.root.setOnClickListener {
//Remove message on the item clicked
messagesList.removeAt(adapterPosition)
notifyItemRemoved(adapterPosition)
}
}
}
The reason why You get this error is that MessageItemBinding
should not be in Adapter but in ViewHolder class.您收到此错误的原因是MessageItemBinding
不应该在 Adapter 中,而是在 ViewHolder class 中。 You can make RecyclerView like this:您可以像这样制作 RecyclerView:
object MessageDiffCallback : DiffUtil.ItemCallback<Message>()
{
override fun areItemsTheSame(
oldItem: Message,
newItem: Message
): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: Message,
newItem: Message
): Boolean =
oldItem == newItem
}
I assume that Message
is a data class.我假设Message
是数据 class。 You have to create this MessageDiffCallback
and override these 2 methods in a similar way that I did it.您必须创建此MessageDiffCallback
并以与我类似的方式覆盖这两个方法。
Now Create ViewHolder
class:现在创建ViewHolder
class:
class MessageViewHolder private constructor(
private val binding: MessageItemBinding
) : RecyclerView.ViewHolder(binding.root)
{
companion object
{
fun create(parent: ViewGroup): MessageViewHolder
{
val layoutInflater = LayoutInflater.from(parent.context)
val binding = MessageItemBinding.inflate(layoutInflater, parent, false)
return MessageViewHolder(
binding
)
}
}
fun bind(
message: Messaage
)
{
// Here You can do everything.
// You pass the message and based on this You can set up a view and use binding
}
}
And now Adapter class现在适配器 class
class MessageAdapter : ListAdapter<Message, MessageViewHolder>(MessageDiffCallback)
{
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder =
MessageViewHolder.create(parent)
override fun onBindViewHolder(holder: MessageViewHolder, position: Int) =
holder.bind(
message = getItem(position),
)
}
Now You should have a working adapter.现在你应该有一个工作适配器。 To put data in it use messageAdapter.submitList(messages)
in Your Fragment/Activity要将数据放入其中,请在您的片段/活动中使用messageAdapter.submitList(messages)
Maybe not the best answer because it changes Your code and uses a little different logic but it should work better.也许不是最好的答案,因为它会更改您的代码并使用一些不同的逻辑,但它应该会更好。 You can check google sample code here or take codelab here .您可以在此处查看google 示例代码或在此处获取codelab 。 It is free after signing up注册后免费
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.