You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Firebase实时数据库聊天应用:消息送达状态背景切换实现

实现Firebase聊天消息发送状态的背景切换

需求说明

用户发送消息时,受网络速度影响可能延迟写入数据库,需要实现:

  • 消息未成功发送到数据库时,界面显示深色背景
  • 消息成功送达数据库后,自动切换为蓝色背景

具体实现步骤

1. 扩展Messages数据模型

给Messages类新增isSent布尔字段,用来标记消息发送状态,同时支持Firebase的序列化/反序列化:

public class Messages {
    private String message;
    private String time;
    private String date;
    private String type;
    private String from;
    private boolean isSent; // 新增发送状态标记

    // Firebase序列化需要空构造函数
    public Messages() {}

    // 带参构造函数,默认未发送
    public Messages(String message, String time, String date, String type, String from) {
        this.message = message;
        this.time = time;
        this.date = date;
        this.type = type;
        this.from = from;
        this.isSent = false;
    }

    // Getter & Setter
    public boolean isSent() {
        return isSent;
    }

    public void setSent(boolean sent) {
        isSent = sent;
    }

    // 其他原有字段的Getter/Setter...
}

2. 修改SendMessage方法,本地优先展示消息

在ChatActivity的SendMessage方法中,先将未发送状态的消息添加到本地列表并刷新UI,再执行Firebase写入操作:

private void SendMessage() {
    final String messageText = messageınputtext.getText().toString();
    if (TextUtils.isEmpty(messageText)) {
        return;
    }

    // 1. 生成当前时间日期(复用原有逻辑)
    Calendar calFordDate = Calendar.getInstance();
    SimpleDateFormat currentDate = new SimpleDateFormat("dd-MMMM-yyyy");
    String saveCurrentDate = currentDate.format(calFordDate.getTime());

    Calendar calFordTime = Calendar.getInstance();
    SimpleDateFormat currentTime = new SimpleDateFormat("HH:mm aa");
    String saveCurrentTime = currentTime.format(calFordTime.getTime());

    // 2. 创建本地待发送消息,添加到列表并刷新UI
    Messages tempMessage = new Messages(messageText, saveCurrentTime, saveCurrentDate, "text", messageSenderID);
    tempMessage.setSent(false);
    messagesList.add(tempMessage);
    messagesAdapter.notifyItemInserted(messagesList.size() - 1);
    usermessageslist.scrollToPosition(messagesList.size() - 1);
    messageınputtext.setText(""); // 清空输入框

    // 3. 执行Firebase数据库写入
    String messagesenderref = "message/" + messageSenderID + "/" + messageReceiverID;
    String messagereceiverref = "message/" + messageReceiverID + "/" + messageSenderID;

    DatabaseReference usermessagekeyref = Rootref.child("message")
            .child(messageSenderID).child(messageReceiverID).push();
    final String messagepushid = usermessagekeyref.getKey();

    Map<String, Object> messageTextBody = new HashMap<>();
    messageTextBody.put("message", messageText);
    messageTextBody.put("time", saveCurrentTime);
    messageTextBody.put("date", saveCurrentDate);
    messageTextBody.put("type", "text");
    messageTextBody.put("from", messageSenderID);
    messageTextBody.put("isSent", true); // 写入数据库时标记为已发送

    Map<String, Object> messageBodyDetails = new HashMap<>();
    messageBodyDetails.put(messagesenderref + "/" + messagepushid, messageTextBody);
    messageBodyDetails.put(messagereceiverref + "/" + messagepushid, messageTextBody);

    Rootref.updateChildren(messageBodyDetails).addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            // 4. 更新本地消息的发送状态,刷新UI
            int lastIndex = messagesList.size() - 1;
            Messages sentMessage = messagesList.get(lastIndex);
            sentMessage.setSent(true);
            messagesAdapter.notifyItemChanged(lastIndex);
        } else {
            String errorMsg = task.getException().getMessage();
            Toast.makeText(ChatActivity.this, "发送失败: " + errorMsg, Toast.LENGTH_SHORT).show();
        }
    });
}

3. 修改MessagesAdapter,根据状态切换背景

在MessagesAdapter的onBindViewHolder方法中,根据isSent字段设置不同的背景资源:

@Override
public void onBindViewHolder(@NonNull final MessageViewHolder messageViewHolder, final int i) {
    String messageSenderID = mAuth.getCurrentUser().getUid();
    Messages messages = userMessagesList.get(i);
    String fromUserID = messages.getFrom();

    messageViewHolder.ReceiverMessageText.setVisibility(View.INVISIBLE);
    messageViewHolder.SenderMessageText.setVisibility(View.INVISIBLE);

    if (fromUserID.equals(messageSenderID)) {
        messageViewHolder.SenderMessageText.setVisibility(View.VISIBLE);
        // 根据发送状态切换背景
        if (messages.isSent()) {
            messageViewHolder.SenderMessageText.setBackgroundResource(R.drawable.sendermessage_blue);
        } else {
            messageViewHolder.SenderMessageText.setBackgroundResource(R.drawable.sendermessage_dark);
        }
        messageViewHolder.SenderMessageText.setTextColor(Color.WHITE);
        messageViewHolder.SenderMessageText.setText(messages.getMessage());
        messageViewHolder.txt_seen.setVisibility(View.VISIBLE);

        // 原有已读状态逻辑...
    } else {
        // 接收方消息原有逻辑不变...
    }

    // 日期显示原有逻辑不变...
}

4. 创建背景Drawable资源

在res/drawable目录下创建两个背景文件:

  • sendermessage_dark.xml(未发送状态深色背景)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#424242"/>
    <corners android:radius="16dp"/>
    <padding android:left="16dp" android:top="8dp" android:right="16dp" android:bottom="8dp"/>
</shape>
  • sendermessage_blue.xml(已发送状态蓝色背景)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#2196F3"/>
    <corners android:radius="16dp"/>
    <padding android:left="16dp" android:top="8dp" android:right="16dp" android:bottom="8dp"/>
</shape>

内容的提问来源于stack exchange,提问作者Muratcan Yıldız

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 04:06:25