簡體   English   中英

lateinit 屬性綁定尚未初始化

[英]lateinit property binding has not been initialized

我知道有類似的問題,但我只是找不到類似的東西,我一直在研究新的東西來學習,在將 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)

它說我必須初始化綁定,但我不知道把它放在哪里。

這是代碼。

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

您沒有初始化binding object,因為您將其定義為lateinit,那么您應該定義它。

這通常在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
    )
}

更新

您需要在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)
        }
    }
}

您收到此錯誤的原因是MessageItemBinding不應該在 Adapter 中,而是在 ViewHolder class 中。 您可以像這樣制作 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
}

我假設Message是數據 class。 您必須創建此MessageDiffCallback並以與我類似的方式覆蓋這兩個方法。

現在創建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
    }
}

現在適配器 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),
            )
}

現在你應該有一個工作適配器。 要將數據放入其中,請在您的片段/活動中使用messageAdapter.submitList(messages)


也許不是最好的答案,因為它會更改您的代碼並使用一些不同的邏輯,但它應該會更好。 您可以在此處查看google 示例代碼或在此處獲取codelab 注冊后免費

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM