2015-05-16 4 views
-1

Я нашел тот же вопрос в I used synchronized list, and i still get ConcurrentModificationException, но я не нашел правильного ответа.Почему я использовал синхронизированный список и все еще получаю ConcurrentModificationException

Вот как я определен мой synchronized список:

private List<ActionItemClickListener> actionItemClickListeners = Collections.synchronizedList(new ArrayList<ActionItemClickListener>()); 

А вот как я использовал его:

@Override 
public void onBackPressed() { 
    boolean isConsume = false; 
    synchronized (actionItemClickListeners) { 
     //ConcurrentModificationException occur here 
     for (ActionItemClickListener listener : actionItemClickListeners) { 
      isConsume = isConsume | listener.onSystemBackPressed(); 
     } 
    } 
    if(!isConsume) { 
     pendingFragment = null; 
     pendingTag = null; 
     currentFragmentTag = null; 
     super.onBackPressed(); 
    } 
} 
public void addActionItemClickListener(ActionItemClickListener listener) { 
     synchronized (actionItemClickListeners) { 
      if (listener != null) 
       actionItemClickListeners.add(listener); 
     } 
} 

public void removeActionItemClickListener(ActionItemClickListener listener) { 
     synchronized (actionItemClickListeners) { 
      if (listener != null) 
       actionItemClickListeners.remove(listener); 
     } 
} 

Почему я все еще получаю ConcurrentModificationException ???

+1

Можете ли вы рассказать нам, где вы получаете исключение? Кроме того, что такое 'super.onBackPressed();'? –

+2

@ReutSharabani, является обратным вызовом android, вызванным os, когда нажата кнопка возврата – Blackbelt

+1

@ReutSharabani Я прокомментировал код: 'super.onBackPressed()' супервызов, мой класс распространяется из класса 'Activity'. –

ответ

2

Ваш ConcurrentModificationException не является проблемой нити. Он забрасывается, потому что вы изменяете список, итерации через него.

for (ActionItemClickListener listener : actionItemClickListeners) { 
    isConsume = isConsume | listener.onSystemBackPressed(); 
} 

Проблема заключается в том, что listener.onSystemBackPressed(); звонит removeActionItemClickListener, который пытается изменить actionItemClickListeners, которые вы в процессе итерации. Попытка изменить список, который вы перебор причинит ConcurrentModificationException

Как исправить

Не видя остальную часть кода, я могу только догадываться о том, как это исправить, но вы можете использовать iterator.next(), iterator.hasNext() и iterator.remove() для прокрутки и удаления слушателя соответственно. Вам нужно будет либо передать iterator через onSystemBackPressed(), либо removeActionItemClickListener, что немного уродливо, или onSystemBackPressed() вернуть логическое значение, указывающее, следует ли удалить слушателя.

final Iterator<String> iterator = actionItemClickListeners.iterator(); 
while (iterator.hasNext()) { 
    final String listener = iterator.next(); 
    final boolean removeListener = listener.onSystemBackPressed(); 
    if (removeListener) { 
     iterator.remove(); 
    } 
    isConsume = isConsume | removeListener; 
} 

К сожалению, похоже, что вы используете возвращаемое значение onSystemBackPressed() для чего-то еще, так что не может работать.

+0

Благодарим за объяснение. Можете ли вы помочь мне найти решение для моего дела? –

+0

@ mr.icetea Добавлено возможное решение для ответа. Однако, трудно сказать, будет ли это полезно, не имея более подробной информации. В любом случае вы можете использовать «Итератор», как указано выше, чтобы удалить из списка, итерации через него, так что, надеюсь, поможет привести вас к решению. – pathfinderelite

Смежные вопросы