【问题标题】:ListView chat message for FirebaseFirebase 的 ListView 聊天消息
【发布时间】:2018-08-01 21:47:29
【问题描述】:

我创建了一个涉及与其他人聊天的应用程序,为了让聊天活动更令人赏心悦目,我创建了一个ListView 来更改每条消息的 UI。当我发送消息时,第一条消息会出现并正确显示,但是如果我发送另一条消息,它将覆盖 listView 中的前一条消息,而不是仅仅向列表视图添加另一个值,这是我的代码:

聊天活动:

private void append_chat_conversation(DataSnapshot dataSnapshot) {
        for (DataSnapshot ds : dataSnapshot.getChildren()) {
            Log.e("Chat details: ", String.valueOf(ds));
            chat_username = dataSnapshot.child("username").getValue(String.class);
            chat_msg = dataSnapshot.child("message").getValue(String.class);

            Chat chat = new Chat(chat_username, chat_msg);
            ArrayList<Chat> chatList = new ArrayList<>();
            chatList.add(chat);

            chatListAdapter adapter = new chatListAdapter(this, R.layout.chat_message, chatList);
            mListView.setAdapter(adapter);
            Log.e("Chat username: ", "" + chat_username);
            Log.e("Chat message: ", "" + chat_msg);

        }
}

聊天列表适配器:

public class chatListAdapter extends ArrayAdapter<Chat> {

    private Context mContext;
    int mResource;
    TextView usernameTV, messageTV;

    public chatListAdapter(Context context, int resource, ArrayList<Chat> objects) {
        super(context, resource, objects);
        mContext = context;
        mResource = resource;

    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String username = getItem(position).getUsername();
        String message = getItem(position).getMessage();

        Chat chat = new Chat(username, message);

        LayoutInflater inflater = LayoutInflater.from(mContext);
        convertView = inflater.inflate(mResource, parent, false);

        usernameTV = convertView.findViewById(R.id.username_chat);
        messageTV = convertView.findViewById(R.id.message_chat);

        usernameTV.setText(username);
        messageTV.setText(message);

        return convertView;
    }
}

我不会添加其他代码(getter 和 setter 或单个消息的实际布局),因为我认为这不是问题。如果您需要其他任何东西,请告诉我,我确定我在这里做了一些愚蠢的事情来实现这一点,

谢谢,内森

编辑:

我终于找到了如何在不覆盖此代码的情况下添加到列表视图:

private void append_chat_conversation(DataSnapshot dataSnapshot) {
        for (DataSnapshot ds : dataSnapshot.getChildren()) {
            Log.e("Chat details: ", String.valueOf(ds));
            chat_username = dataSnapshot.child("username").getValue(String.class);
            chat_msg = dataSnapshot.child("message").getValue(String.class);

            Chat chat = new Chat(chat_username, chat_msg);
            chatList.add(chat);
            Log.e("Chat username: ", "" + chat_username);
            Log.e("Chat message: ", "" + chat_msg);
        }
        adapter.notifyDataSetChanged();
    }

数组列表和 adpater 是顶部的公共变量,但它仍然显示消息两次。我仍然需要为此找到解决方法。感谢您的帮助

【问题讨论】:

    标签: java android firebase listview firebase-realtime-database


    【解决方案1】:

    您可以使用 FirebaseListAdapter 显示来自 firebase 的消息,并将自定义布局应用于列表中的消息。

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        Query messages = database.getReference("chatrooms").child(sessionId).child("messages");
    
        FirebaseListOptions<Message> options = new FirebaseListOptions.Builder<Message>().setQuery(messages, Message.class).setLayout(R.layout.message).build();
    
        ListView messageList = chatActivity.findViewById(R.id.message_list);
        adapter = new FirebaseListAdapter<Message>(options){
            @Override
            protected void populateView(View v, Message model, int position) {
                // Get references to the views of message.xml
                TextView messageText = v.findViewById(R.id.message_text);
                TextView messageUser = v.findViewById(R.id.message_user);
                TextView messageTime = v.findViewById(R.id.message_time);
    
                // Set their text
                messageText.setText(model.getMessageBody());
                messageUser.setText(model.getUser());
    
                // Format the date before showing it
                messageTime.setText(DateFormat.format("dd-MM-yyyy (HH:mm:ss)",
                        model.getTime()));
            }
        };
    
        messageList.setAdapter(adapter);
        adapter.startListening();
    

    在此处查看更多信息:https://code.tutsplus.com/tutorials/how-to-create-an-android-chat-app-using-firebase--cms-27397

    【讨论】:

    • 谢谢你的评论我去看看
    • 感谢您的回答。我一直在为此苦苦挣扎。我刚刚错过了那行 adapter.startListening();
    【解决方案2】:

    要解决这个问题,只需使用以下代码行:

    private void append_chat_conversation(DataSnapshot dataSnapshot) {
            ArrayList<Chat> chatList = new ArrayList<>();
            for (DataSnapshot ds : dataSnapshot.getChildren()) {
                chatList.add(ds.getValue(Chat.class));
            }
            chatListAdapter adapter = new chatListAdapter(this, R.layout.chat_message, chatList);
            mListView.setAdapter(adapter);
    }
    

    您的代码中的问题是您在每次迭代时都创建了一个 ArrayList 的新实例,最终每次列表中只有一个项目。

    编辑:

    看到这个,你的数据库引用应该是这样的:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference keyRef = rootRef.child("matches").child("1").child("-LluNpbfFgzFclI7cdAS").child("messages");
    

    【讨论】:

    • 您好,我尝试了您的代码并收到此错误:com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.wasd.opposites.Chat
    • 这意味着您使用了错误的DatabaseReference。请添加您的数据库结构。
    • 感谢您的帮助,非常感谢,数据库参考指向这个地方,我将通过图像发送它:imgur.com/a/e0F8PkS(每次用户发送消息它都会创建一个随机字符串并且在该节点中包含消息和用户名:imgur.com/a/muf5Rqo
    • 在这种情况下,您应该使用数据库引用keyRef,如我更新的答案中所示。现在可以用了吗?
    • 我知道我必须使用 keyRef 引用,但是,每条消息都有自己的密钥,因此它在技术上必须是动态的。我不能硬编码一个值,因为它只是一堆随机值,如下所示:imgur.com/a/Bl7QuBl 有没有办法解决这个问题?
    【解决方案3】:

    尝试像这样重新排列:

    private void append_chat_conversation(DataSnapshot dataSnapshot) {
        ArrayList<Chat> chatList = new ArrayList<>();
        for (DataSnapshot ds : dataSnapshot.getChildren()) {
            Log.e("Chat details: ", String.valueOf(ds));
            chat_username = dataSnapshot.child("username").getValue(String.class);
            chat_msg = dataSnapshot.child("message").getValue(String.class);
    
            Chat chat = new Chat(chat_username, chat_msg);
            chatList.add(chat);
            Log.e("Chat username: ", "" + chat_username);
            Log.e("Chat message: ", "" + chat_msg);
        }
        chatListAdapter adapter = new chatListAdapter(this, R.layout.chat_message, chatList);
        mListView.setAdapter(adapter);
    }
    

    已编辑:

    private void append_chat_conversation(DataSnapshot dataSnapshot) {
        chatListAdapter adapter = (chatListAdapter)mListView.getAdapter();
    
        chat_username = dataSnapshot.child("username").getValue(String.class);
        chat_msg = dataSnapshot.child("message").getValue(String.class);
        Log.e("Chat username: ", "" + chat_username);
        Log.e("Chat message: ", "" + chat_msg);
        Chat chat = new Chat(chat_username, chat_msg);
    
        adapter.add(chat);
        adapter.notifyDataSetChanged();
    }
    

    【讨论】:

    • 非常感谢,我试试看
    • 我试着按照你说的重新排列,现在消息在列表视图中出现了两次,然后如果我添加另一条消息,它会再次被覆盖,但会再次显示两次。
    • 谢谢,我试试看,我需要 for 循环,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2021-11-13
    相关资源
    最近更新 更多