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