使用Android和OpenGL ES 1.1的ConcurrentModificationException

时间:2012-05-01 14:20:15

标签: android opengl-es concurrency

我对OpenGL编程很陌生,我制作了一个简单的引擎来简化我的绘图工作。现在我想基于加速度计进行转换,并且我得到 ConcurrentModificationException

这是对象类:

public class IbnRushdObject
{
    /** The graphical object to show */
    private Mesh mesh = null;

    /** List of transformations to be executed upon this object */
    private List<IbnRushdTransformation> transformations;

    /** Lock to prevent modification of the list when executing the transformations and viceversa */
    private final ReentrantLock lock = new ReentrantLock();

    /**
     * Initializes this IbnRushd object with a mesh
     * @param mesh
     */
    public IbnRushdObject(Mesh mesh)
    {
        this.mesh = mesh;
    }

    /**
     * Adds a transformation to be performed on this object<br>
     * The transformation does not take place until {@link #moveDraw(GL10)} is called
     * @param trans
     */
    public void addTransformation(IbnRushdTransformation trans)
    {
        try
        {
            lock.lock();
            if (transformations == null)
            {
                transformations = new LinkedList<IbnRushdTransformation>();         
            }
            transformations.add(trans);
        }
        finally
        {
            lock.unlock();
        }
    }

    /**
     * Executes transformations for this object and draws it
     * @param gl
     */
    public void moveDraw(GL10 gl)
    {
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

        try
        {
            lock.lock();
            for(IbnRushdTransformation trans: transformations) // ConcurrentMoificationException thrown here
            {
                trans.execute(gl);
                if (!trans.isPermanent())
                {
                    transformations.remove(trans);
                }
            }
        }
        finally
        {
            lock.unlock();
        }

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        mesh.draw(gl);
    }
}

moveDraw()方法仅从

调用
@Override
public void onDrawFrame(GL10 gl)
{
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glClearColor(0, 0.5f, 0.5f, 1.0f);

    for(IbnRushdObject object : objectQueue)
    {
        object.moveDraw(gl);
    }
}

,其中包含要绘制的所有对象的列表。

这是侦听加速度计事件的代码。监听器方法是 onEventChange()

public class IbnRushdOrientation implements ServiceListener<Orientation>
{
    private IbnRushdObject object = null;

    public IbnRushdOrientation(IbnRushdObject obj)
    {
        object = obj;
    }

    @Override
    public void onEventChange(Orientation arg0)
    {
        IbnRushdRotation hrot = new IbnRushdRotation();
        hrot.setFixed(0, 0, 1, 0);
        hrot.setIncremental((float)arg0.getHorizontalAngle());
        hrot.setPermanent(false);

        IbnRushdRotation vrot = new IbnRushdRotation();
        vrot.setFixed(0, 1, 0, 0);
        vrot.setIncremental((float)arg0.getVerticalAngle());
        vrot.setPermanent(false);

        object.addTransformation(hrot);
        object.addTransformation(vrot);
    }
}

我在 moveDraw()方法的for(IbnRushdTransformation trans: transformations)上获得了ConcurrentModificationException。

有什么想法吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

当您迭代它时,无法从列表中删除对象。这就是引起异常的原因。

如果使用迭代器而不是for循环(transformations.iterator())迭代列表,则可以在迭代时调用iterator.remove()以安全地删除它。

“请注意,Iterator.remove是在迭代期间修改集合的唯一安全方法;如果在迭代进行过程中以任何其他方式修改基础集合,则行为未指定。”

http://java.sun.com/docs/books/tutorial/collections/interfaces/collection.html