GLSurfaceView queueEvent的作用

使用OpenGL的时候,我们需要一个工作线程来调用OpenGL方法。GLSurfaceView为此创建了一个独立的渲染线程,这也是所有实现GLSurfaceView.Renderer中的方法(这些方法包装了调用OpenGL的细节,简化了开发)的工作线程。所以我们不需要关心线程相关的东西,只需要编写需要实现的方法即可。

基于线程原因,我们不能简单的在UI线程中调用OpenGL方法,例如,事件分发的方法中我们直接调用Renderer中的方法。除此之外,我们还需要考虑线程安全问题,即同时被UI线程和OpenGL渲染线程读写的变量。

使用queueEvent(),则完全不必担心上述问题,因为最终所有方法都是在GLSUrfaceView.Renderer中的方法中调用的,也就是在渲染线程中使用的。

看看源码中该函数的调用流程:

/**
 * Queue a runnable to be run on the GL rendering thread. This can be used
 * to communicate with the Renderer on the rendering thread.
 * Must not be called before a renderer has been set.
 * @param r the runnable to be run on the GL rendering thread.
 */
public void queueEvent(Runnable r) {
    mGLThread.queueEvent(r);
}

mGLThread即是渲染线程。从注释中即可知,这个方法是用来和渲染线程进行通信的。

/**
 * Queue an "event" to be run on the GL rendering thread.
 * @param r the runnable to be run on the GL rendering thread.
 */
public void queueEvent(Runnable r) {

    synchronized(sGLThreadManager) {
        mEventQueue.add(r);
        sGLThreadManager.notifyAll();
    }

}

这个函数的核心代码就上面这两句。可见,当渲染线程空闲的时候,这个方法可以与渲染线程交互并唤醒渲染线程。

private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();

private void guardedRun() throws InterruptedException {

    Runnable event = null;

    while (true) {
        synchronized (sGLThreadManager) {
            while (true) {
                if (mShouldExit) {
                    return;
                }

                if (! mEventQueue.isEmpty()) {
                    event = mEventQueue.remove(0);
                    break;
                }
                
                ...
                
                if (event != null) {
                    event.run();
                    event = null;
                    continue;
                }    

                ...
                
                view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);                
                
                ...
                
                view.mRenderer.onSurfaceChanged(gl, w, h);
                
                ...
                
                view.mRenderer.onDrawFrame(gl);

guardedRun即是渲染线程的工作渲染函数的入口,从上面的函数选摘可知,会在渲染线程的mRenderer方法调用之前调用mEventQueue方法。

queueEvent的典型用法是根据用户输入改变mRenderer中的状态,然后在mRenderer.onDrawFrame中使用新的状态。

参考:http://stackoverflow.com/questions/25388929/android-opengl-queueevent-why

原文地址:https://www.cnblogs.com/fordreamxin/p/5318843.html