Сообщение чата ListView для Firebase

Я создал приложение, которое включает в себя чат с другими людьми, и чтобы сделать чат более приятным для глаз, я создал ListView, чтобы изменять пользовательский интерфейс каждого сообщения. Когда я отправляю сообщение, первое сообщение появляется и отображается правильно, но если я отправляю другое сообщение, оно переопределяет предыдущее сообщение в listView вместо того, чтобы просто добавлять другое значение в представление списка, вот мой код:

ChatActivty:

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;
    }
}

Я не буду добавлять другие части кода (методы получения и установки или фактический макет отдельных сообщений), потому что я не думаю, что это проблема. Дай мне знать, если тебе еще что-нибудь понадобится, я уверен, что делаю что-то глупое, чтобы это произошло,

Спасибо, Натан

Обновлено:

Наконец-то я узнал, как добавить в список, не переопределяя его с помощью этого кода:

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 являются общедоступной переменной вверху, однако сообщение по-прежнему отображается дважды. Мне все еще нужно исправить это. Спасибо за помощь

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
1 293
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать 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

Спасибо за комментарий, посмотрю

user9722951 02.08.2018 12:43

Спасибо за ответ. Я боролся с этим. Я просто пропустил линейный адаптер. StartListening ();

Raju Vadnala 18.01.2020 12:14

Попробуйте переставить так:

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();
}

Большое спасибо, я попробую

user9722951 02.08.2018 12:43

Я попытался изменить порядок, как вы сказали, и теперь сообщение появляется дважды в представлении списка, а затем, если я добавляю другое сообщение, оно снова переопределяется, но снова показывает его дважды.

user9722951 02.08.2018 13:00

Спасибо, я попробую, мне нужен цикл for, правда?

user9722951 03.08.2018 14:42
Ответ принят как подходящий

Чтобы решить эту проблему, просто используйте только следующие строки кода:

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: не удается преобразовать объект типа java.lang.String в тип com.wasd.opposites.Chat

user9722951 02.08.2018 13:07

Это означает, что вы используете не тот DatabaseReference. Пожалуйста, добавьте структуру вашей базы данных.

Alex Mamo 02.08.2018 13:22

Спасибо за помощь, я очень ценю это, ссылка на базу данных указывает на это место, я отправлю его через изображение: imgur.com/a/e0F8PkS (каждый раз, когда пользователь отправляет сообщение, он создает случайную строку, и в этом узле у него есть сообщение и имя пользователя в нем: imgur.com/a/muf5Rqo

user9722951 02.08.2018 13:27

В этом случае вы должны использовать ссылку на базу данных keyRef, как в моем обновленном ответе. А теперь работает?

Alex Mamo 02.08.2018 13:42

Я понимаю, что мне нужно использовать ссылку keyRef, однако каждое сообщение получает собственный ключ, поэтому технически оно должно быть динамическим. Я не могу жестко запрограммировать значение, так как это просто набор случайных значений, как показано здесь: imgur.com/a/Bl7QuBl есть ли способ обойти это?

user9722951 02.08.2018 13:45

Под узлом messages есть 2 сообщения, и это точно будет работать. Если вы говорите о первом жестко запрограммированном идентификаторе -LluNpbfFgzFclI7cdAS, я просто привел вам пример. Когда вы нажимаете этот идентификатор, вам нужно сохранить его в переменной, чтобы использовать его в качестве ссылки, верно?

Alex Mamo 02.08.2018 13:51

Это сработает, но только для человека, который отправил сообщение, поскольку он единственный, у кого нажата клавиша, у другого не будет этого ключа, потому что он был создан на стороне его клиента, если это имеет смысл.

user9722951 02.08.2018 14:00

В этом случае вам следует изменить структуру вашей базы данных. Вы не можете добиться этого с помощью своей реальной схемы. Вы должны создать узел, на котором вам нужно размещать все сообщения в разговоре, верно?

Alex Mamo 02.08.2018 15:36

Дело в том, как работает мое приложение, сообщения являются временными, и они удаляются примерно через 5 минут, пользователи сопоставляются друг с другом, и у них есть 5 минут, чтобы поговорить друг с другом, затем он заканчивается, и весь матч удаляется

user9722951 02.08.2018 18:16

Да, я понимаю, но это единственный способ решения вашей проблемы.

Alex Mamo 02.08.2018 18:22

Если вы считаете, что мой ответ вам помог, примите его, нажав на галочку слева под стрелками для голосования. Должен поменять цвет на зеленый. Я бы оценил это. Спасибо!

Alex Mamo 03.08.2018 10:34

Другие вопросы по теме