Android:ConcurrentModificationException 持续存在

Android: ConcurrentModificationException persisting

我有 2 个列表 suggestedFriendsallSuggestedFriends

我使用迭代器 运行 通过第一个列表并从此列表中删除项目。在途中,如果第二个列表中仍有项目,则应从中删除项目。我使用第二个迭代器(在 SafeRemove 方法中)只是为了从第二个列表中删除项目。

问题:有时我会在行 if (allSuggestedFriends.size() > 0) { 中收到 ConcurrentModificationException,即使我使用迭代器来提议删除项目。

我应该使用迭代器来请求大小吗?我不认为这是可能的(?!)

synchronized (suggestedFriends) {
    for (final Iterator<User> suggestedFriendsIterator = suggestedFriends.iterator(); suggestedFriendsIterator.hasNext();) {
        User friend = suggestedFriendsIterator.next();
        if (friend.userId == request.getUserId()) {
            final int index = suggestedFriends.indexOf(friend);
            if (status) {
                ((FragmentActivityExt) context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(suggestedFriends.size() > 0) {
                            suggestedFriendsIterator.remove();
                        }
                        notifyDataSetChanged();
                        if (allSuggestedFriends.size() > 0) {
                            suggestedFriends.add(2, allSuggestedFriends.get(0));
                            SafeRemove(allSuggestedFriends, allSuggestedFriends.get(0));
                            notifyDataSetChanged();
                        }
                        if (suggestedFriends.size() == 1) {
                            // FIXME workaround to fix list height as wrap_content is not supported by RecyclerView at the moment
                            //set to fit 1 element
                            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mListView.getLayoutParams();
                            params.height = EndoUtility.dpToPx(context, 70);
                            mListView.setLayoutParams(params);
                        }

                        if (suggestedFriends.size() == 0) {
                            EventBus.getDefault().post(new NoMoreSuggestedFriendsEvent());
                        }
                    }
                });
            } else {
                if (mListView != null) {
                    ((FragmentActivityExt) context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(context, R.string.networkProblemToast, Toast.LENGTH_LONG).show();
                            ((SuggestedFriendView) mListView.getChildAt(index)).reset();
                        }
                    });
                }
            }
            break;
        }
    }
}

使用第二个迭代器的 SafeRemove 方法:

private void SafeRemove(List<User> list, User friend) {
    Iterator<User> iter = list.iterator();

    while (iter.hasNext()) {
        User user = iter.next();

        if (user.userId == friend.userId)
            iter.remove();
    }
}

更新:

SafeRemove(allSuggestedFriends, allSuggestedFriends.get(0)); 行周围添加 synchronized 是否是解决方案?像那样:

...
synchronized (allSuggestedFriends) {
    SafeRemove(allSuggestedFriends, allSuggestedFriends.get(0));
}
...

或者更好的是,在 SafeRemove 方法中?像那样:

private void SafeRemove(List<User> list, User friend) {
    synchronized (list) {
        Iterator<User> iter = list.iterator();

        while (iter.hasNext()) {
            User user = iter.next();

            if (user.userId == friend.userId)
                iter.remove();
        }            
    }
}

嗯,由于我的问题被标记为可能重复,所以我没有得到任何答复。这很不幸,因为我很确定讨论中的案例与建议的 link.

不同

尽管如此,我没有使用 synchronized implemented 关键字(正如我自己在更新中所建议的那样),而是实现了一个并行计数器,当列表完成加载时它会调整到列表大小,并且然后在项目从列表中删除时递减。这消除了 allSuggestedFriends.size() 检查,这是 ConcurrentModificationException 发生的地方。

...
private int allSuggestedFriendsCount;
...
// allSuggestedFriends loads items
...
allSuggestedFriendsCount = allSuggestedFriends.size();
...

...
if (allSuggestedFriendsCount > 0) {
    suggestedFriends.add(2, allSuggestedFriends.get(0));
    SafeRemove(allSuggestedFriends, allSuggestedFriends.get(0));
    notifyDataSetChanged();
}
...

private void SafeRemove(List<User> list, User friend) {
    Iterator<User> iter = list.iterator();

    while (iter.hasNext()) {
        User user = iter.next();
        if (user.userId == friend.userId) {
            iter.remove();
            allSuggestedFriendsCount--;
        }
    }
}