Функцию onDraw ConcurrentModification андроид ()
У меня проблема с приложением для android.
У меня есть поток, который постоянно перебирает список или фигуры, обновляет их позиции и иногда удаляет элемент из списка. В конце цикла while потока он вызывает postInvalidate (), чтобы вызвать перерисовку.
Вот код, в котором происходит модификация ArrayList.
Iterator<Shape> iterator = this.myList.iterator();
while (iterator.hasNext()) {
Shape nextShape = iterator.next();
nextShape.move();
if(condition) {
iterator.remove()
}
}
Метод onDraw использует цикл for each для рисования каждого из этих элементов. Я получаю параллельную модификацию в метод onDraw, несмотря только на изменение списка через итератор. Я пробовал CopyOnWriteArrayList и Collections.синхронизировано с теми же результатами.
Любая помощь будет признательна.
1 ответ:
Есть несколько способов решить эту проблему. Можно было бы использовать синхронизированный блок в потоке и в onDraw, но это помешало бы 2-му потоку работать одновременно с потоком пользовательского интерфейса.
Я думаю, что лучший способ для вас-использовать две коллекции. Ваш код должен выглядеть следующим образомonDraw(){ synchronized(myList){ //Do your draw code. Get the iterator inside this block } } threadFunction(){ List threadList; while(1){ //Update threadList, which holds all the objects synchronized(myList){ myList = threadList.copy(); //Do a deep copy, don't just copy over the reference } postInvalidate(); } }
Это заставит вашу функцию draw работать с копией списка, сделанного в конце итерации. Если вы работаете с глубокой копией, у вас не будет никаких проблем с синхронизацией поскольку поток не изменяет один и тот же список. Синхронизированные блоки остановят поток от перезаписи копии функции draw во время рисования. Единственная оставшаяся проблема заключается в том, что перезапись списка в потоке будет висеть до тех пор, пока не будет выполнена ничья, но поскольку обновление его чаще, чем это, все равно не будет отображаться на экране, я думаю, что это приемлемо.