Вставить объект в начало RecyclerView, отображающего запрос Firebase

Я веду чат, используя Firebase для хранения сообщений и RecyclerView для их отображения. Согласно приведенному ниже коструктору адаптера, когда RecyclerView инициализируется, последние 50 сообщений запрашиваются из Cloud Firestore и располагаются в порядке убывания по временной метке Unix. Затем я использую setStackFromEnd (true) в своем чате, чтобы изменить порядок их отображения, так как самые новые сообщения должны быть внизу, а новые сообщения добавляются в список сообщений адаптера с помощью messageList.add (0, message)

Это представляет проблему. В onBindViewHolder ранее приемлемые:

Message message = messageList.get(position);

holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");

Больше не работает, потому что сообщение, вводимое в RecyclerView, будет повторением самого последнего сообщения при загрузке RecyclerView (то есть в позиции 0). то есть:

  • сообщение первое
  • сообщение первое
  • сообщение первое
  • сообщение первое

Вместо того:

  • сообщение первое
  • сообщение два
  • сообщение третье
  • сообщение четвертое

Где «message one» - самое последнее сообщение при создании RecyclerView. Заменив это на:

Message message = messageList.get(0);

holder.message.setText(message.getMessage());
holder.author.setText(message.getAuthor() + ":");

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

Конструктор адаптера:

public ChatRecyclerViewAdapter(Context mContext, ArrayList<String> mMessage, ArrayList<String> mAuthor, String mRoomID, FirebaseFirestore firestore) {
        messageList = new ArrayList<>();
        firestore = FirebaseFirestore.getInstance();
        mCollection = firestore.collection(mRoomID + "_messages");
        Query query = mCollection.orderBy("timestamp", Query.Direction.DESCENDING).limit(50);
        query.addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {
                for (DocumentChange documentChange : queryDocumentSnapshots.getDocumentChanges()) {
                    switch (documentChange.getType()) {
                        case ADDED:
                            documentChange.getDocument();
                            Message message = documentChange.getDocument().toObject(Message.class);
                            messageList.add(0,message);
                            notifyItemInserted(messageList.size());
                    }
                }
            }
        });

Попытка запросить следующий набор сообщений старого набора при прокрутке:

 query.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                if (queryDocumentSnapshots.size() > 0) {
                    //Get the last visible document
                    DocumentSnapshot lastVisible = queryDocumentSnapshots.getDocuments().get(messageList.size()-1);

                    //Construct a new query starting at this document and get the next batch of messages
                    Query next = mCollection.orderBy("timestamp", Query.Direction.DESCENDING).startAfter(lastVisible).limit(20);
                    next.get();
                }
            }
        });
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в вашем коде заключается в том, что вы сортируете по убыванию, используя Unix timestamp, а не объект Date. Чтобы заставить его работать, я рекомендую вам изменить способ хранения метки времени на Date. По этому поводу см. Мой ответ из этого Почта, где я объяснил, как этого можно добиться с помощью POJO class или Map.

Здесь вы можете найти руководство о том, как создать Приложение для чата, где я объяснил то же самое, что вы ищете. См. Снимок экрана ниже:

В моем коде я использовал в качестве запроса следующую строку кода:

val query = rootRef!!
    .collection("messages")
    .document(roomId)
    .collection("roomMessages")
    .orderBy("sentAt", Query.Direction.ASCENDING)

Извините, я упустил некоторые важные детали. В конечном итоге я хочу иметь возможность разбивать сообщения согласно документации на страницы, чтобы получать больше сообщений, когда пользователь прокручивает самое старое сообщение. Для этого я добавил начало своего кода. Я отсортировал по убыванию, чтобы самые последние сообщения загружались первыми, когда я использовал .limit (). Сортировка по возрастанию с ограничением загружает самые старые сообщения и ничего более, причем самое старое сообщение находится в позиции [0], которое всегда будет видно при загрузке.

andrewedgar 06.10.2018 18:08

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

Alex Mamo 08.10.2018 09:44

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

Alex Mamo 08.10.2018 09:45

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

Alex Mamo 08.10.2018 09:46

Спасибо. Я попробую это и опубликую новый вопрос, если у меня все еще будут проблемы.

andrewedgar 08.10.2018 14:19

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