我的 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 提供的解决方案。
您在检查
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
}
}