获取 java.lang.IndexOutOfBoundsException:对于我的适配器代码,索引 8 超出长度 8 的范围

问题描述 投票:0回答:1

我的 logcat 看起来像: logcat 应用程序崩溃

  class ChatAdapter(private val currentUserId: Int) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private val messages = mutableListOf<Message>()
    private var isTypingIndicatorVisible = false

    fun updateMessages(newMessages: List<Message>) {
        messages.addAll(newMessages)
        notifyDataSetChanged()
    }
    private val MESSAGE_SENT = 1
    private val MESSAGE_RECEIVED = 2
    private val TYPING_INDICATOR = 3

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            MESSAGE_SENT -> {
                val binding = ItemMessageSentBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                SentMessageViewHolder(binding)
            }
            MESSAGE_RECEIVED -> {
                val binding = ItemMessageReceivedBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                ReceivedMessageViewHolder(binding)
            }
            TYPING_INDICATOR -> {
                val binding = ItemTypingIndicatorBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                TypingIndicatorViewHolder(binding)
            }
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val message = messages[position]
        when (holder.itemViewType) {
            MESSAGE_SENT -> {
                (holder as SentMessageViewHolder).bind(message)
            }
            MESSAGE_RECEIVED -> {
                (holder as ReceivedMessageViewHolder).bind(message)
            }
            TYPING_INDICATOR -> {
                (holder as TypingIndicatorViewHolder).bind(message)
            }
        }
    }


    override fun getItemCount(): Int {
        return messages.size + if (isTypingIndicatorVisible) 1 else 0
    }

    override fun getItemViewType(position: Int): Int {
        val message = messages[position]
        return if (isTypingIndicatorVisible && position == messages.size) {
            TYPING_INDICATOR
        } else if (message.senderEmail == currentUserId.toString()) {
            MESSAGE_SENT
        } else {
            MESSAGE_RECEIVED
        }
    }

    fun showTypingIndicator(isVisible: Boolean) {
        isTypingIndicatorVisible = isVisible
        notifyDataSetChanged()
    }

    inner class TypingIndicatorViewHolder(private val binding: ItemTypingIndicatorBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(message: Message) {
            binding.tvTyping.visibility = View.VISIBLE
        }
    }
    inner class SentMessageViewHolder(private val binding: ItemMessageSentBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(message: Message) {
            binding.tvMsgSent.text = message.content
            val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
            val date = dateFormat.parse(message.date)
            binding.tvDateTime.text = SimpleDateFormat("hh:mm a", Locale.getDefault()).format(date)
        }
    }

    inner class ReceivedMessageViewHolder(private val binding: ItemMessageReceivedBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(message: Message) {
            binding.tvMsgReceived.text = message.content
            val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
            val date = dateFormat.parse(message.date)
            binding.tvDateTime.text = SimpleDateFormat("hh:mm a", Locale.getDefault()).format(date)
        }
    }
}

这是我的聊天屏幕适配器代码。我使用 3 种视图类型来发送消息、接收消息和显示打字指示器。 该活动工作正常,但当我打开键盘并输入某些内容时,它会崩溃并出现我在 logcat 屏幕截图中提到的错误。

我尝试更改 getItemViewType 和 getItemCount 逻辑。 以及 stackOverFlow 上针对 IndexOutOfBoundsException 提供的解决方案。

android kotlin android-recyclerview mobile-development
1个回答
1
投票

您在检查

messages[position]
之前先访问
position == messages.size
。当
position
等于
messages.size
时,
message[position]
抛出。

    override fun getItemViewType(position: Int): Int {
        val message = messages[position]
        return if (isTypingIndicatorVisible && position == messages.size) {
            TYPING_INDICATOR
        } else if (message.senderEmail == currentUserId.toString()) {
            MESSAGE_SENT
        } else {
            MESSAGE_RECEIVED
        }
    }

解决办法是先检查

messages.size

    override fun getItemViewType(position: Int): Int {
        return if (isTypingIndicatorVisible && position == messages.size) {
            TYPING_INDICATOR
        } else {
            val message = messages[position]
            if (message.senderEmail == currentUserId.toString()) {
                MESSAGE_SENT
            } else {
                MESSAGE_RECEIVED
            }
        }
    }

或者如果您发现嵌套缩进伤害您的眼睛,请使用 nullable

    override fun getItemViewType(position: Int): Int {
        val message = getOrNull[position]
        return if (isTypingIndicatorVisible && message == null) {
            TYPING_INDICATOR
        } else if (message?.senderEmail == currentUserId.toString()) {
            MESSAGE_SENT
        } else {
            MESSAGE_RECEIVED
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.