【问题标题】:android studio java.util.ConcurrentModificationExceptionandroid 工作室 java.util.ConcurrentModificationException
【发布时间】:2020-06-16 16:03:15
【问题描述】:

我不断从 Firebase 收到这个 ConcurrentModificationException

  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”等),但我仍然遇到错误。现在我不知道我可以改变什么来解决这个问题。 这是我当前的代码:

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

                                }
                            }

还有更扩展的代码sn-p:

公共类 ChatFragment 扩展片段 {

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

}

【问题讨论】:

    标签: android firebase


    【解决方案1】:

    根据 ArrayList 的 OracleDocs

    这个类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在任何结构上被修改 迭代器创建后的时间,除了通过 迭代器自己的删除或添加方法,迭代器会抛出一个 并发修改异常。因此,面对并发 修改,迭代器快速而干净地失败,而不是 在不确定的时间冒着任意的、不确定的行为的风险 未来。

    为了解决这个问题,我关注了ConcurrentModificationException,它对解决此类异常有很好的解释。

    我们如何避免:

    1. 如果您使用的是 JDK1.5 或更高版本,则可以使用 ConcurrentHashMap 和 CopyOnWriteArrayList 类。这是推荐的方法 避免并发修改异常。 (我采用了这种方法)
    2. 避免多线程中的 ConcurrentModificationException 环境您可以将列表转换为数组,然后迭代 数组。这种方法适用于中小型列表 但是如果列表很大,那么它会对性能产生很大影响。
    3. 您可以在迭代时锁定列表,方法是将其放入 同步块。不推荐这种方法,因为它会 停止使用多线程的好处。

    【讨论】:

      【解决方案2】:

      是的,您找到了问题所在 - 避免 ConcurrentModificationException -

      您可以使用迭代器从底层集合对象中删除/添加对象。但在这种情况下,您可以从列表中删除同一个对象,而不是任何其他对象。

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

      希望这会对你有所帮助。

      【讨论】:

        猜你喜欢
        • 2020-11-13
        • 2017-07-21
        • 2016-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多