Я получаю ConcurrentModificationException при создании приложения чата - PullRequest
0 голосов
/ 07 января 2019

При отображении фрагмента недавних чатов в приложении я извлекаю свои чаты из firebase и отфильтрую чаты по их получателю и senderID в объекте чата для отображения последних чатов.

Проблема говорит об исключении ConcurrentModificationException в ArrayList, и похоже, что из-за сложности поиска идентификатора в массиве, в котором это произошло, мне нужно решение, чтобы минимизировать сложность фильтрации чата.

  // private List<String> stringList; Declaration at top 
    stringList = new ArrayList<>();
    firebaseUser = FirebaseAuth.getInstance().getCurrentUser();

    databaseReference = FirebaseDatabase.getInstance().getReference("BaatCheet/Chats/");
    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            //userModelList.clear();
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                MessageModel messageModel = dataSnapshot1.getValue(MessageModel.class);

                if (messageModel.getSender().equals(firebaseUser.getUid())){
                  stringList.add(messageModel.getReceiver());
                }
                if (messageModel.getReceiver().equals(firebaseUser.getUid())){
                    stringList.add(messageModel.getSender());
                }
            }
            readChat();
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });

Функция чтения чата

  private void readChat() {

    userModelList = new ArrayList<>();
    databaseReference = FirebaseDatabase.getInstance().getReference("BaatCheet/Users/");

    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            userModelList.clear();
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                UserModel userModel = dataSnapshot1.getValue(UserModel.class);

                for (String id: stringList){
                    if (userModel.getId().equals(id)){
                        if (userModelList.size() !=0){
                            for (UserModel userModel1 : userModelList){
                                if (!userModel.getId().equals(userModel1.getId())){
                                    userModelList.add(userModel);
                                    Log.d("DataAdded",userModel.getId());
                                } // If the existing list don't have same value for sender and reciever
                            } // end of inner userModel
                        } else {
                            userModelList.add(userModel);
                            Log.d("DataAdded",userModel.getId());
                        } // end of else
                    }   // end of userModel id equals string id
                }   // end of String is loop
            }   // end of DataSnapshot loop

            usersAdapter = new UsersAdapter(userModelList);
            recyclerView.setAdapter(usersAdapter);


        } // end of onDataChange

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });
}// end of readChat()

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

Ответы [ 2 ]

0 голосов
/ 07 января 2019

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

Приведенный ниже код предназначен для создания нового узла каждый раз, когда пользователь отправляет сообщение, он будет обновлять узел, если recieverID отличается.

dbrefChatList = FirebaseDatabase.getInstance().
                getReference("BaatCheet/ChatList/")
                .child(senderuserID)
                .child(receiveruserID);

        dbrefChatList.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if (!dataSnapshot.exists()){
                    dbrefChatList.child("id").setValue(receiveruserID);
                }
            }
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
            }
        });

Таким образом, ChatList является классом модели, который содержит одну строку с именем «id», и этот идентификатор будет использоваться для поиска в узле.

Приведенный ниже код предназначен для фрагмента ChatFragment, который извлекает chatList из firebase и устанавливает данные в представление переработчика.

      // private List<ChatList> chatList; Declaration at top
    chatListList = new ArrayList<>();
    firebaseUser = FirebaseAuth.getInstance().getCurrentUser();

    databaseReference = FirebaseDatabase
            .getInstance()
            .getReference("BaatCheet/ChatList")
            .child(firebaseUser.getUid());

    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            chatListList.clear();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                    ChatList chatList = snapshot.getValue(ChatList.class);
                    chatListList.add(chatList);
                }
                myChatList();
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });

Функция myChatList действует как функция readChat в постановке задачи.

 private void myChatList() {

    userModelList = new ArrayList<>();
    databaseReference = FirebaseDatabase.getInstance().getReference("BaatCheet/Users/");
    databaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            userModelList.clear();
            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                UserModel userModel = snapshot.getValue(UserModel.class);
                for (ChatList chatList : chatListList){
                    if (userModel.getId().equals(chatList.getId())){
                        userModelList.add(userModel);
                    }
                }
            }
            usersAdapter = new UsersAdapter(userModelList);
            recyclerView.setAdapter(usersAdapter);
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });

}
0 голосов
/ 07 января 2019

В следующем фрагменте кода:

for (UserModel userModel1 : userModelList){
   if (!userModel.getId().equals(userModel1.getId())){
        userModelList.add(userModel);
        Log.d("DataAdded",userModel.getId());
    } // If the existing list don't have same value for sender and reciever
} //

Вы изменяете userModelList, перебирая userModelList. Это недопустимо и является причиной ConcurrentModificationException.

Существует несколько способов упростить логику, самый простой (хотя и не самый лучший) будет преобразовать этот цикл foreach в простой цикл for i.

for (int i = 0; i< userModelList.size(); i++) {
    UserModel userModel1 = userModelList.get(i);
    if (!userModel.getId().equals(userModel1.getId())){
       userModelList.add(userModel);
       Log.d("DataAdded",userModel.getId());
    } // If the existing list don't have same value for sender and reciever
} //
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...