JetChat/src/main/java/com/lotus_lab/jetchat/ui/ChatAdapter.java

173 lines
8.3 KiB
Java
Raw Normal View History

2025-05-07 16:38:58 +08:00
package com.lotus_lab.jetchat.ui;
2025-05-07 19:39:10 +08:00
import android.util.Log; // 导入 Log 类
2025-05-07 16:38:58 +08:00
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.lotus_lab.jetchat.R;
2025-05-07 19:39:10 +08:00
import com.lotus_lab.jetchat.data.ChatMessage; // 确保 ChatMessage 类有 role 属性
2025-05-07 16:38:58 +08:00
import java.util.ArrayList;
import java.util.List;
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.MessageViewHolder> {
2025-05-07 19:39:10 +08:00
private static final String ADAPTER_TAG = "ChatAdapter"; // 用于日志记录的标签
2025-05-07 16:38:58 +08:00
private final List<ChatMessage> messages;
2025-05-07 19:39:10 +08:00
// 可以在 ChatMessage 类中定义这些常量,或者在这里定义,以避免硬编码字符串 "assistant" 和 "user"
2025-05-07 16:38:58 +08:00
// public static final String ROLE_USER = "user";
// public static final String ROLE_ASSISTANT = "assistant";
public ChatAdapter(List<ChatMessage> initialMessages) {
this.messages = new ArrayList<>(initialMessages);
}
public void clearMessages() {
int oldSize = messages.size();
this.messages.clear();
notifyItemRangeRemoved(0, oldSize);
2025-05-07 19:39:10 +08:00
Log.d(ADAPTER_TAG, "消息已清空。旧数量: " + oldSize);
2025-05-07 16:38:58 +08:00
}
public List<ChatMessage> getMessages() {
2025-05-07 19:39:10 +08:00
return new ArrayList<>(this.messages); // 返回列表的副本
2025-05-07 16:38:58 +08:00
}
public void setMessages(List<ChatMessage> newMessages) {
this.messages.clear();
2025-05-07 19:39:10 +08:00
if (newMessages != null) { // 为安全起见,添加 null 检查
2025-05-07 16:38:58 +08:00
this.messages.addAll(newMessages);
}
2025-05-07 19:39:10 +08:00
notifyDataSetChanged(); // 在生产环境中,考虑使用 DiffUtil 以获得更好的性能
Log.d(ADAPTER_TAG, "消息已设置。新数量: " + this.messages.size());
2025-05-07 16:38:58 +08:00
}
public void addMessage(ChatMessage message) {
if (message == null) {
2025-05-07 19:39:10 +08:00
Log.w(ADAPTER_TAG, "尝试添加一个 null 消息。");
2025-05-07 16:38:58 +08:00
return;
}
this.messages.add(message);
notifyItemInserted(messages.size() - 1);
2025-05-07 19:39:10 +08:00
Log.d(ADAPTER_TAG, "消息已添加。角色: " + (message.role != null ? message.role : "null") +
", 内容: '" + (message.content != null ? message.content.substring(0, Math.min(message.content.length(), 50))+"..." : "null") + // 截断过长的内容日志
"'. 新数量: " + messages.size());
2025-05-07 16:38:58 +08:00
}
@NonNull
@Override
public MessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
2025-05-07 19:39:10 +08:00
Log.d(ADAPTER_TAG, "onCreateViewHolder 调用,视图类型: " + viewType);
2025-05-07 16:38:58 +08:00
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message, parent, false);
return new MessageViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MessageViewHolder holder, int position) {
ChatMessage message = messages.get(position);
Log.i(ADAPTER_TAG, "-----------------------------------------------------");
2025-05-07 19:39:10 +08:00
Log.i(ADAPTER_TAG, "onBindViewHolder - 位置: " + position);
2025-05-07 16:38:58 +08:00
if (message == null) {
2025-05-07 19:39:10 +08:00
Log.e(ADAPTER_TAG, "位置 " + position + " 的 Message 对象为 NULL。正在隐藏项目。");
holder.itemView.setVisibility(View.GONE); // 如果消息为 null则隐藏该项目
2025-05-07 16:38:58 +08:00
return;
}
2025-05-07 19:39:10 +08:00
// 记录 ChatMessage 对象的原始角色和内容
Log.d(ADAPTER_TAG, "原始消息角色: '" + message.role + "'");
Log.d(ADAPTER_TAG, "原始消息内容: '" + message.content + "'");
2025-05-07 16:38:58 +08:00
if (message.role == null || message.content == null) {
holder.itemView.setVisibility(View.GONE);
2025-05-07 19:39:10 +08:00
Log.w(ADAPTER_TAG, "位置 " + position + " 的消息角色或内容为 null。角色: '" + message.role + "', 内容: '" + message.content + "'. 正在隐藏项目。");
2025-05-07 16:38:58 +08:00
return;
}
2025-05-07 19:39:10 +08:00
// 如果数据有效,确保项目可见
2025-05-07 16:38:58 +08:00
holder.itemView.setVisibility(View.VISIBLE);
2025-05-07 19:39:10 +08:00
// 可选:如果在调试中为整个项目设置了交替颜色,则重置项目背景
2025-05-07 16:38:58 +08:00
// holder.itemView.setBackground(null);
2025-05-07 19:39:10 +08:00
// 关键检查:将角色与 "assistant" 和 "user" 进行比较
// 确保这些字符串与 ChatMessage.role 中的内容完全匹配
2025-05-07 16:38:58 +08:00
boolean isAiMessage = "assistant".equals(message.role);
2025-05-07 19:39:10 +08:00
// boolean isUserMessage = "user".equals(message.role); // 也可以显式检查用户消息
2025-05-07 16:38:58 +08:00
2025-05-07 19:39:10 +08:00
Log.d(ADAPTER_TAG, "处理后的角色: '" + message.role + "', 是否为AI消息 = " + isAiMessage);
2025-05-07 16:38:58 +08:00
2025-05-07 19:39:10 +08:00
// 直接设置文本内容,它已经包含了模型标识(例如 "[模型: xxx]\n实际内容..."
2025-05-07 16:38:58 +08:00
holder.tvMessage.setText(message.content);
2025-05-07 19:39:10 +08:00
holder.tvMessage.setVisibility(View.VISIBLE); // 确保 TextView 可见
2025-05-07 16:38:58 +08:00
2025-05-07 19:39:10 +08:00
// 将文本颜色和背景重置为 XML 或基本样式中的默认值,
// 以防 RecyclerView 的 ViewHolder 缓存了之前的调试样式。
// holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), android.R.color.black)); // 或者你的 R.color.your_default_text_color
// holder.tvMessage.setBackground(null); // 让下面的特定背景优先
2025-05-07 16:38:58 +08:00
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) holder.tvMessage.getLayoutParams();
if (isAiMessage) {
2025-05-07 19:39:10 +08:00
Log.d(ADAPTER_TAG, "正在为AI消息应用样式: '" + message.content.substring(0, Math.min(message.content.length(), 20)) + "...'");
2025-05-07 16:38:58 +08:00
holder.ivAiAvatar.setVisibility(View.VISIBLE);
holder.ivUserAvatar.setVisibility(View.GONE);
params.horizontalBias = 0.0f; // AI 消息靠左
holder.tvMessage.setBackground(
ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.bg_reply_message_bubble)
);
2025-05-07 19:39:10 +08:00
// 示例:如果需要,可以为 AI 消息设置不同的文本颜色
2025-05-07 16:38:58 +08:00
// holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.ai_text_color));
2025-05-07 19:39:10 +08:00
} else { // 目前假设任何非 AI 消息都是用户消息
// 如果有其他角色(如 "system"),则需要更具体的检查。
Log.d(ADAPTER_TAG, "正在为用户消息应用样式: '" + message.content.substring(0, Math.min(message.content.length(), 20)) + "...'");
2025-05-07 16:38:58 +08:00
holder.ivAiAvatar.setVisibility(View.GONE);
2025-05-07 19:39:10 +08:00
holder.ivUserAvatar.setVisibility(View.GONE); // 根据你的 item_message.xml用户头像默认为 GONE
2025-05-07 16:38:58 +08:00
params.horizontalBias = 1.0f; // 用户消息靠右
holder.tvMessage.setBackground(
ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.bg_user_message_bubble)
);
2025-05-07 19:39:10 +08:00
// 示例:如果需要,可以为用户消息设置不同的文本颜色
2025-05-07 16:38:58 +08:00
// holder.tvMessage.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.user_text_color));
}
holder.tvMessage.setLayoutParams(params);
2025-05-07 19:39:10 +08:00
Log.i(ADAPTER_TAG, "已完成为位置 " + position + " 应用样式");
2025-05-07 16:38:58 +08:00
Log.i(ADAPTER_TAG, "-----------------------------------------------------");
}
@Override
public int getItemCount() {
return messages.size();
}
static class MessageViewHolder extends RecyclerView.ViewHolder {
ImageView ivAiAvatar;
ImageView ivUserAvatar;
TextView tvMessage;
MessageViewHolder(@NonNull View itemView) {
super(itemView);
ivAiAvatar = itemView.findViewById(R.id.iv_ai_avatar);
2025-05-07 19:39:10 +08:00
ivUserAvatar = itemView.findViewById(R.id.iv_user_avatar); // 虽然用户头像默认GONE但ID还是需要的
2025-05-07 16:38:58 +08:00
tvMessage = itemView.findViewById(R.id.tv_message);
2025-05-07 19:39:10 +08:00
if (ivAiAvatar == null) Log.e(ADAPTER_TAG, "MessageViewHolder: ivAiAvatar 为 null!");
// ivUserAvatar 在你的布局中可能确实不存在或ID不同如果它总是GONE可以不查找或处理null
// if (ivUserAvatar == null) Log.e(ADAPTER_TAG, "MessageViewHolder: ivUserAvatar 为 null!");
if (tvMessage == null) Log.e(ADAPTER_TAG, "MessageViewHolder: tvMessage 为 null!");
2025-05-07 16:38:58 +08:00
}
}
}