android студия java .util.ConcurrentModificationException - PullRequest
0 голосов
/ 04 марта 2020

Я получаю это исключение ConcurrentModificationException от Firebase

  Process: com.example.myclass, PID: 9145
java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at com.example.myclass.Fragments.ChatFragment$2.onDataChange(ChatFragment.java:109)
    at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.2.1:75)
    at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.2.1:63)
    at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.2.1:55)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6682)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

Я уже несколько раз менял код (например, использовал addAll вне l oop et c.) Но я все еще получаю ошибку. Теперь у меня нет идей, что я мог бы изменить, чтобы это исправить. Вот мой текущий код:

    private void readChat(){
    mUsers = new ArrayList<>();

    reference = FirebaseDatabase.getInstance().getReference("Users");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mUsers.clear();

            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                User user = snapshot.getValue(User.class);

                //display 1 users from chat
                for (String id : userlist){
                    if (user.getId().equals(id)){
                        if (mUsers.size()!=0){        
                            for (User user1 : mUsers){ <<<<<<<<<<<<<<<<<<<THIS ERRORR
                                if(!user.equals(user1.getId())){
                                    mUsers.add(user);

                                }
                            }
                        }else{
                            mUsers.add(user);

                               }
                    }
                }

            }

            userAdapter = new UserAdapter(getContext(),mUsers);
            recyclerView.setAdapter(userAdapter);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Toast.makeText(getContext(), "database error", Toast.LENGTH_SHORT).show();
        }
    });
}

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

                                for (User user1 : mUsers){
                                if(!user.equals(user1.getId())){
                                    mUsers.add(user);

                                }
                            }

И более расширенный фрагмент кода:

publi c, класс ChatFragment extends Fragment {

private RecyclerView recyclerView;

private UserAdapter userAdapter;
private List<User>mUsers;

private FirebaseUser fuser;
private DatabaseReference reference;

private List<String>userlist;

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_chat,container,false);

    recyclerView = view.findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

    fuser = FirebaseAuth.getInstance().getCurrentUser();

    userlist = new ArrayList<>();

    reference = FirebaseDatabase.getInstance().getReference("Chats");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            userlist.clear();

            for (DataSnapshot snapshot :dataSnapshot.getChildren()){
                Chat chat = snapshot.getValue(Chat.class);

                if(chat.getSender().equals(fuser.getUid())){
                    userlist.add(chat.getReceiver());

                }
                if (chat.getReceiver().equals(fuser.getUid())){
                    userlist.add(chat.getSender());
                }
            }

            readChat();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });



    return view;




}

private void readChat(){
    mUsers = new ArrayList<>();

    reference = FirebaseDatabase.getInstance().getReference("Users");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mUsers.clear();

            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                User user = snapshot.getValue(User.class);

                //display 1 users from chat
                for (String id : userlist){
                    if (user.getId().equals(id)){
                        if (mUsers.size()!=0){
                            for (User user1 : mUsers){
                                if(!user.equals(user1.getId())){
                                    mUsers.add(user);

                                }
                            }
                        }else{
                            mUsers.add(user);

                               }
                    }
                }

            }

            userAdapter = new UserAdapter(getContext(),mUsers);
            recyclerView.setAdapter(userAdapter);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Toast.makeText(getContext(), "database error", Toast.LENGTH_SHORT).show();
        }
    });
}

}

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Да, у вас есть проблема - чтобы избежать ConcurrentModificationException -

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

    Iterator<String> iterator = mUsers.iterator();
    while (iterator.hasNext()) {
    String value = iterator.next();
        mUsers.add("user1");
        mUsers.add("user2");
    }

Надеюсь, это поможет вам.

0 голосов
/ 04 марта 2020

Согласно OracleDocs для ArrayList

Итераторы, возвращаемые методами итератора этого класса и listIterator, работают быстро: если список структурно изменяется в любое время после итератора создается любым способом, кроме как через собственные методы удаления или добавления итератора, итератор создает исключение ConcurrentModificationException. Таким образом, перед лицом одновременной модификации, итератор быстро и чисто не работает, вместо того, чтобы рисковать произвольным, неопределенным поведением c в неопределенное время в будущем.

Чтобы решить эту проблему, Я следовал этому ConcurrentModificationException , и у него есть очень хорошее объяснение разрешения такого исключения.

Как мы можем избежать:

  1. Если вы используете JDK1.5 или выше тогда вы можете использовать классы ConcurrentHashMap и CopyOnWriteArrayList. Это рекомендуемый подход, чтобы избежать исключения одновременной модификации. (я придерживался этого подхода)
  2. Чтобы избежать ConcurrentModificationException в многопоточной среде Вы можете преобразовать список в массив, а затем выполнить итерации в массиве. Этот подход хорошо работает для небольшого или среднего размера списка, но если список большой, это сильно повлияет на производительность.
  3. Вы можете заблокировать список во время итерации, поместив его в синхронизированный блок. Этот подход не рекомендуется, потому что он прекратит преимущества многопоточности.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...