英文:
I am having a FATAL EXCEPTION: main Process: umo.com.players, PID: 29401
问题
以下是翻译好的部分:
我遇到了一个 FATAL EXCEPTION: main
进程:umo.com.players,PID:29401
如何解决 Fatal Exception 的错误
我从未遇到过这种错误
我需要尝试并完成这个项目 java.util.ConcurrentModificationException
这是我的日志记录
请帮忙
2020-10-14 15:52:11.691 29401-29401/? E/AndroidRuntime: FATAL EXCEPTION: main
进程:umo.com.players,PID:29401
java.util.ConcurrentModificationException
在 java.util.ArrayList$Itr.next(ArrayList.java:860)
在 umo.com.players.Home.ChatFragment$2.onDataChange(ChatFragment.java:98)
在 com.google.android.gms.internal.zzbpx.zza(Unknown Source:13)
在 com.google.android.gms.internal.zzbqx.zzZV(Unknown Source:2)
在 com.google.android.gms.internal.zzbra$1.run(Unknown Source:63)
在 android.os.Handler.handleCallback(Handler.java:790)
在 android.os.Handler.dispatchMessage(Handler.java:99)
在 android.os.Looper.loop(Looper.java:164)
在 android.app.ActivityThread.main(ActivityThread.java:6739)
在 java.lang.reflect.Method.invoke(Native Method)
在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:449)
在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
这是聊天片段
public class ChatFragment extends Fragment {
private RecyclerView recyclerView;
private UserAdapter userAdapter;
private List<User> mUsers;
FirebaseUser fuser;
DatabaseReference reference;
private List<String> usersList;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_messages, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
fuser = FirebaseAuth.getInstance().getCurrentUser();
usersList = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("chats");
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if (chat.getSender().equals(fuser.getUid())){
usersList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fuser.getUid())){
usersList.add(chat.getSender());
}
}
readchats();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
return view;
}
private void readchats() {
mUsers = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("users");
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
for (String id : usersList){
if (user.getUser_id().equals(id)){
if (mUsers.size() !=0 ){
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
mUsers.add(user);
}
}
}else {
mUsers.add(user);
}
}
}
}
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
英文:
I am having a FATAL EXCEPTION: main
Process: umo.com.players, PID: 29401
How do you solve the error of Fatal Exception
I have never had any kind of this error
I need to try and finish this project java.util.ConcurrentModificationException
here is my logcat
Please help
2020-10-14 15:52:11.691 29401-29401/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: umo.com.players, PID: 29401
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at umo.com.players.Home.ChatFragment$2.onDataChange(ChatFragment.java:98)
at com.google.android.gms.internal.zzbpx.zza(Unknown Source:13)
at com.google.android.gms.internal.zzbqx.zzZV(Unknown Source:2)
at com.google.android.gms.internal.zzbra$1.run(Unknown Source:63)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6739)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:449)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
here is chat fragment
public class
ChatFragment
extends Fragment {
private RecyclerView recyclerView;
private UserAdapter userAdapter;
private List<User> mUsers;
FirebaseUser fuser;
DatabaseReference reference;
private List<String> usersList;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_messages, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
fuser = FirebaseAuth.getInstance().getCurrentUser();
usersList = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("chats");
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if (chat.getSender().equals(fuser.getUid())){
usersList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fuser.getUid())){
usersList.add(chat.getSender());
}
}
readchats();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
return view;
}
private void readchats() {
mUsers = new ArrayList<>();
reference = FirebaseDatabase.getInstance().getReference("users");
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
for (String id : usersList){
if (user.getUser_id().equals(id)){
if (mUsers.size() !=0 ){
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
mUsers.add(user);
}
}
}else {
mUsers.add(user);
}
}
}
}
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
答案1
得分: 1
这个异常意味着你正在尝试在某段代码正在迭代列表时对其进行结构性修改。
这是ArrayList
的默认行为,并可以通过以下文档支持:
> 该类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后,任何时候以任何方式对列表进行了结构性修改,除非是通过迭代器自己的remove或add方法,否则迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速而干净地失败,而不是冒着在未来某个不确定的时间面临任意的、不确定的行为的风险。
>
> 请注意,由于在存在不同步的并发修改的情况下很难做出任何硬性保证,迭代器的快速失败行为无法得到保证。快速失败迭代器基于最大努力原则在抛出ConcurrentModificationException。因此,编写一个依赖于此异常来确保正确性的程序是错误的:迭代器的快速失败行为只应用于检测错误。
有关所涉及文档的链接在此。
现在根据我从共享代码中获取的信息,你有一个名为
private List<String> usersList;
的普通列表,你在这里对它进行了修改:
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if (chat.getSender().equals(fuser.getUid())){
usersList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fuser.getUid())){
usersList.add(chat.getSender());
}
}
readchats();
}
这里有两种类型的修改:
- 清空列表
- 添加新元素
与此同时,你在以下代码段中迭代了所涉及的列表:
for (String id : usersList){
if (user.getUser_id().equals(id)){
if (mUsers.size() !=0 ){
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
mUsers.add(user);
}
}
}else {
mUsers.add(user);
}
}
}
由于这两段代码是以异步方式执行的,没有保证在某人修改列表的同时,另一个人将在其上进行迭代。
我建议您重新检查代码以解决这个问题,或者找到其他迭代所涉及列表的方法。
英文:
This exception means that you are attempting to structurally modify a list while some piece of code is in the process of iterating it.
This is the default behavior of the ArrayList
and can be backed up by the following piece of documentation:
> The iterators returned by this class's iterator and listIterator
> methods are fail-fast: if the list is structurally modified at any
> time after the iterator is created, in any way except through the
> iterator's own remove or add methods, the iterator will throw a
> ConcurrentModificationException. Thus, in the face of concurrent
> modification, the iterator fails quickly and cleanly, rather than
> risking arbitrary, non-deterministic behavior at an undetermined time
> in the future.
>
> Note that the fail-fast behavior of an iterator cannot be guaranteed
> as it is, generally speaking, impossible to make any hard guarantees
> in the presence of unsynchronized concurrent modification. Fail-fast
> iterators throw ConcurrentModificationException on a best-effort
> basis. Therefore, it would be wrong to write a program that depended
> on this exception for its correctness: the fail-fast behavior of
> iterators should be used only to detect bugs.
Link to the document in question here.
Now from what I can tell from the share code, you can a common list named
private List<String> usersList;
Which you modify here:
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
if (chat.getSender().equals(fuser.getUid())){
usersList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fuser.getUid())){
usersList.add(chat.getSender());
}
}
readchats();
}
There are two kind of modifications here:
- Clearing the list
- Adding new elements
At the same time you iterate the list in question in this code segment:
for (String id : usersList){
if (user.getUser_id().equals(id)){
if (mUsers.size() !=0 ){
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
mUsers.add(user);
}
}
}else {
mUsers.add(user);
}
}
}
Since both piece of code are executed in an asynchronous manner, there is no guarantee that someone will be modifying the list while someone else will be iterating over it.
I suggest you revisit your code to address this or find some other way of iterating the list in question.
答案2
得分: 0
你遇到了ConcurrentModificationException
,这是因为你正在尝试在for循环内部修改列表。可以通过以下几种方式解决这个问题:
-
你可以使用CopyOnWriteArrayList作为
mUsers
列表的类型。 -
或者你可以在循环内部创建新的列表来进行操作
for (User user1 : new ArrayList<>(mUsers)){...}
-
或者你可以通过为新项目添加临时列表的方式以更经济的方式解决
List<User> usersToBeAdded = new ArrayList<User>();
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
usersToBeAdded.add(user);
}}
mUsers.addAll(usersToBeAdded);
英文:
You are getting ConcurrentModificationException
because you are trying to modify the list inside the for loop.
This can be solved in several ways:
-
You can use CopyOnWriteArrayList as a type for
mUsers
list. -
Or you can just create new List to be used inside the loop
for (User user1 : new ArrayList<>(mUsers)){...}
-
Or you can solve it in more economical way by adding temporary list for new items
List<User> usersToBeAdded = new ArrayList<User>();
for (User user1 : mUsers){
if (!user.getUser_id().equals(user1.getUser_id())){
usersToBeAdded.add(user);
}}
mUsers.addAll(usersToBeAdded);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论