使用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