Android:ConcurrentModificationException 持续存在
Android: ConcurrentModificationException persisting
我有 2 个列表 suggestedFriends
和 allSuggestedFriends
。
我使用迭代器 运行 通过第一个列表并从此列表中删除项目。在途中,如果第二个列表中仍有项目,则应从中删除项目。我使用第二个迭代器(在 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--;
}
}
}
我有 2 个列表 suggestedFriends
和 allSuggestedFriends
。
我使用迭代器 运行 通过第一个列表并从此列表中删除项目。在途中,如果第二个列表中仍有项目,则应从中删除项目。我使用第二个迭代器(在 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--;
}
}
}