我正在制作一个游戏,并且在迭代它时删除/修改数组列表时我读了所有关于并发修改异常的内容,但我仍然有问题。
我想在触摸屏幕时删除对象,并且对象x,y与触摸的x,y对齐但是当发生这种情况时,我将触摸的对象放入新的集合中以进行删除,但它会移除(有时)对象但是3-4s之后对我来说没什么意义,并且在10-15s之后也给出了并发修改异常。如果有人注意到我的代码中的任何内容,请告诉我......
public void checkTouch(MotionEvent arg1) {
int x = (int) arg1.getX();
int y = (int) arg1.getY();
synchronized(surfaceHolder){
/*check every creature for the coordinates*/
Iterator<Sprite> it = creature.iterator();
while(it.hasNext())
{
Sprite current = it.next();
int sglX = current.getX();
int sglY = current.getY();
if(sglX>=x && x<=(sglX+current.getWidth())){
if(sglY>=y && y<=(sglY-current.getHeight())){
destroy(current);
break; //when we found one object, don't iterate no more
}
}
}
}
}
和目标方法:
private void destroy(Sprite removed) {
/*adds the creature clicked to the recicle bin to be destroyed*/
recicle.add(removedSeagull); //recicle is the other collection
}
在我在画布上绘制生物之前我称之为creature.removeAll(recicle);
,因此它不会与其他迭代器发生冲突。
这是堆栈跟踪:
07-11 21:06:00.905: E/AndroidRuntime(14221): FATAL EXCEPTION: Thread-83
07-11 21:06:00.905: E/AndroidRuntime(14221): java.util.ConcurrentModificationException
07-11 21:06:00.905: E/AndroidRuntime(14221): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
07-11 21:06:00.905: E/AndroidRuntime(14221): at com.example.creatures.GameView$GameThread.drawCreatures(GameView.java:292)
07-11 21:06:00.905: E/AndroidRuntime(14221): at com.example.creatures.GameView$GameThread.doDraw(GameView.java:283)
07-11 21:06:00.905: E/AndroidRuntime(14221): at com.example.creatures.GameView$GameThread.run(GameView.java:245)
我认为它可能是绘图方法,所以可能是错误,这里是:
private void drawCreatures(Canvas c) {
/*iterate through the array and update all the creatures*/
synchronized(surfaceHolder){
Iterator<Sprite> it = creature.iterator();
while(it.hasNext())
{
Sprite current = it.next();
current.draw(c);
}
}
}
GameThread的run方法在GameView中调用(扩展表面持有者),如下所示:
@Override
public void surfaceCreated(SurfaceHolder arg0) {
thread.setRunning(true);
thread.start();
startTimer(1500);
}
而且线程的run方法是这样的:
@Override
public void run(){
while(run){
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
if (mode == STATE_RUNNING){
doDraw(c);
}
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, don't leave the Surface in an
// inconsistent state
if (c != null) {
/*unlocks the canvas and shows the image drawn by the doDraw method*/
surfaceHolder.unlockCanvasAndPost(c);
}
“drawCreatures”方法在“doDraw”方法中调用。
答案 0 :(得分:2)
如果您对迭代器的过时结果很好,那么您可以使用CopyOnWriteArrayList http://developer.android.com/reference/java/util/concurrent/CopyOnWriteArrayList.html
基本上它确保迭代器显示创建迭代器时存在的内容。唯一的变化是iterator.remove()不能对此列表返回的迭代器起作用。您必须将其从实际列表中删除。
希望有所帮助,
纳格什
答案 1 :(得分:0)
为什么您不使用iterator
的默认方法?
撰写it.remove()
代替destroy(current);