package com.example.livestreaming; import android.graphics.Outline; import android.net.Uri; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import androidx.annotation.NonNull; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.example.livestreaming.databinding.ItemConversationBinding; public class ConversationsAdapter extends ListAdapter { public interface OnConversationClickListener { void onConversationClick(ConversationItem item); } private final OnConversationClickListener onConversationClickListener; public ConversationsAdapter(OnConversationClickListener onConversationClickListener) { super(DIFF); this.onConversationClickListener = onConversationClickListener; } @NonNull @Override public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { ItemConversationBinding binding = ItemConversationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); return new VH(binding, onConversationClickListener); } @Override public void onBindViewHolder(@NonNull VH holder, int position) { holder.bind(getItem(position)); } static class VH extends RecyclerView.ViewHolder { private final ItemConversationBinding binding; private final OnConversationClickListener onConversationClickListener; VH(ItemConversationBinding binding, OnConversationClickListener onConversationClickListener) { super(binding.getRoot()); this.binding = binding; this.onConversationClickListener = onConversationClickListener; } void bind(ConversationItem item) { binding.title.setText(item != null && item.getTitle() != null ? item.getTitle() : ""); binding.lastMessage.setText(item != null && item.getLastMessage() != null ? item.getLastMessage() : ""); binding.timeText.setText(item != null && item.getTimeText() != null ? item.getTimeText() : ""); int unread = item != null ? item.getUnreadCount() : 0; if (unread > 0) { binding.unreadBadge.setVisibility(View.VISIBLE); binding.unreadBadge.setText(unread > 99 ? "99+" : String.valueOf(unread)); } else { binding.unreadBadge.setVisibility(View.GONE); } // 加载头像 loadAvatar(item); binding.getRoot().setOnClickListener(v -> { if (item == null) return; if (onConversationClickListener != null) onConversationClickListener.onConversationClick(item); }); } private void loadAvatar(ConversationItem item) { // TODO: 接入后端接口 - 加载会话对方头像 // 接口路径: GET /api/users/{userId}/avatar 或直接从ConversationItem的avatarUrl字段获取 // 如果ConversationItem对象包含avatarUrl字段,直接使用该URL加载头像 // 如果没有avatarUrl,需要根据会话类型(私信/群聊)调用相应接口获取头像 if (binding.avatar == null) return; // 设置圆形裁剪 setupAvatarOutline(); try { // 优先使用ConversationItem中的avatarUrl(从后端获取) // 尝试从 SharedPreferences 加载用户头像 String avatarUri = binding.avatar.getContext() .getSharedPreferences("profile_prefs", android.content.Context.MODE_PRIVATE) .getString("profile_avatar_uri", null); if (!TextUtils.isEmpty(avatarUri)) { // 尝试解析 URI Uri uri = Uri.parse(avatarUri); // 如果是 file:// 协议,尝试转换为 FileProvider URI if ("file".equals(uri.getScheme())) { try { java.io.File file = new java.io.File(uri.getPath()); if (file.exists()) { uri = FileProvider.getUriForFile( binding.avatar.getContext(), binding.avatar.getContext().getPackageName() + ".fileprovider", file ); } } catch (Exception e) { // 如果转换失败,使用原始 URI } } Glide.with(binding.avatar) .load(uri) .circleCrop() .error(R.drawable.ic_account_circle_24) .placeholder(R.drawable.ic_account_circle_24) .into(binding.avatar); return; } int avatarRes = binding.avatar.getContext() .getSharedPreferences("profile_prefs", android.content.Context.MODE_PRIVATE) .getInt("profile_avatar_res", 0); if (avatarRes != 0) { Glide.with(binding.avatar) .load(avatarRes) .circleCrop() .error(R.drawable.ic_account_circle_24) .placeholder(R.drawable.ic_account_circle_24) .into(binding.avatar); return; } // 如果没有保存的头像,使用默认头像 Glide.with(binding.avatar) .load(R.drawable.ic_account_circle_24) .circleCrop() .into(binding.avatar); } catch (Exception e) { // 如果加载失败,使用默认头像 Glide.with(binding.avatar) .load(R.drawable.ic_account_circle_24) .circleCrop() .into(binding.avatar); } } private void setupAvatarOutline() { if (binding.avatar == null) return; // 设置圆形裁剪,确保在模拟器上也能正常工作 binding.avatar.post(() -> { if (binding.avatar.getWidth() > 0 && binding.avatar.getHeight() > 0) { binding.avatar.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { outline.setOval(0, 0, view.getWidth(), view.getHeight()); } }); binding.avatar.setClipToOutline(true); } }); } } private static final DiffUtil.ItemCallback DIFF = new DiffUtil.ItemCallback() { @Override public boolean areItemsTheSame(@NonNull ConversationItem oldItem, @NonNull ConversationItem newItem) { String o = oldItem.getId(); String n = newItem.getId(); return o != null && o.equals(n); } @Override public boolean areContentsTheSame(@NonNull ConversationItem oldItem, @NonNull ConversationItem newItem) { return oldItem.equals(newItem); } }; }