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




Вы можете использовать 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
Спасибо за ответ. Я боролся с этим. Я просто пропустил линейный адаптер. StartListening ();
Попробуйте переставить так:
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, правда?
Чтобы решить эту проблему, просто используйте только следующие строки кода:
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
Это означает, что вы используете не тот DatabaseReference. Пожалуйста, добавьте структуру вашей базы данных.
Спасибо за помощь, я очень ценю это, ссылка на базу данных указывает на это место, я отправлю его через изображение: imgur.com/a/e0F8PkS (каждый раз, когда пользователь отправляет сообщение, он создает случайную строку, и в этом узле у него есть сообщение и имя пользователя в нем: imgur.com/a/muf5Rqo
В этом случае вы должны использовать ссылку на базу данных keyRef, как в моем обновленном ответе. А теперь работает?
Я понимаю, что мне нужно использовать ссылку keyRef, однако каждое сообщение получает собственный ключ, поэтому технически оно должно быть динамическим. Я не могу жестко запрограммировать значение, так как это просто набор случайных значений, как показано здесь: imgur.com/a/Bl7QuBl есть ли способ обойти это?
Под узлом messages есть 2 сообщения, и это точно будет работать. Если вы говорите о первом жестко запрограммированном идентификаторе -LluNpbfFgzFclI7cdAS, я просто привел вам пример. Когда вы нажимаете этот идентификатор, вам нужно сохранить его в переменной, чтобы использовать его в качестве ссылки, верно?
Это сработает, но только для человека, который отправил сообщение, поскольку он единственный, у кого нажата клавиша, у другого не будет этого ключа, потому что он был создан на стороне его клиента, если это имеет смысл.
В этом случае вам следует изменить структуру вашей базы данных. Вы не можете добиться этого с помощью своей реальной схемы. Вы должны создать узел, на котором вам нужно размещать все сообщения в разговоре, верно?
Дело в том, как работает мое приложение, сообщения являются временными, и они удаляются примерно через 5 минут, пользователи сопоставляются друг с другом, и у них есть 5 минут, чтобы поговорить друг с другом, затем он заканчивается, и весь матч удаляется
Да, я понимаю, но это единственный способ решения вашей проблемы.
Если вы считаете, что мой ответ вам помог, примите его, нажав на галочку слева под стрелками для голосования. Должен поменять цвет на зеленый. Я бы оценил это. Спасибо!
Спасибо за комментарий, посмотрю