您好,登錄后才能下訂單哦!
本文對于runOnGLThread方法的分析主要目的是為了幫助我的課程“拇指接龍游戲”學員更好地理解EasyNDK這個開源框架的使用。借助于這個框架,實現Android JAVA端與Cococ2d-x C++端交互,以及iOS Objective-C端與Cococ2d-x C++端交互將變得異常容易----極大地減少了相關的JNI編程與Objecive-C編程的代碼量。但是,在EasyNDK的Android版本示例中在Java主Activity端存在如下代碼段:
public void ChangeSomethingInCocos() { this.runOnGLThread(new Runnable() { @Override public void run() { AndroidNDKHelper.SendMessageWithParameters("ChangeLabelSelector", null); } }); } |
上述代碼中SendMessageWithParameters方法為什么要運行于runOnGLThread方法中?本文將試圖對這部分代碼進行充分解釋。至于EasyNDK的其他部分的使用就容易理解多了。
一、回顧傳統Android編程中使用的runOnUiThread方法
在android中經常需要用到異步操作,Thread+Handler方式比較繁瑣(當然功能也最為強大),而AsyncTask只能執行一次,很多需求不能滿足(有關AsyncTask用法,請參考我引用的另外一篇博客)。
此時,我們可以試試Activity提供的另外一種簡單的方法runOnUiThread,runOnUiThread可以幫助你在線程中執行UI更新操作。
以下為線程中使用runOnUiThread方法的框架代碼:
MyActivity.this. runOnUiThread(new Runnable() { @Override public void run() { // refresh ui 的操作代碼 } });
這里需要注意:runOnUiThread是Activity中的方法,在我們的工作線程中需要告訴系統是哪個Activity調用,所以前面顯式地指明Activity。
下面為runOnUiThread的宏觀代碼:
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
從代碼可以看到,runOnUiThread首先判斷是否是UI線程,不是的話就post,如果是的話就正常運行該線程。只要經過主線程中的Handler.post或者postDelayed處理,線程Runnable都可以被加入到UI主線程的消息循環中,并為主線程的Handler所檢索并調用。有關的Handler運行原理,請參考我引用的其他幾篇博客文章。
值得注意的是,本節中的runOnUiThread方法適合于從子線程中更新普通Android View內容時調用。但是,當我們在Android下進行OpenGL ES開發時,也就是本文關注的cocos2d-x開發時,需要使用另一個方法,即下文要討論的runOnGLThread。
二、Cocos2d-x編程中的runOnGLThread方法
cocos2d-x開發中,一旦涉及到Android平臺移植自然要與Cocos2dxActivity這個東西打交道。Cocos2dxActivity是cocos2d-x開發團隊的成果,它是一個抽象類,具體形式如下:
public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {//...}
我們知道,cocos2d-x是運行于OpenGL平臺的。Android平臺下進行OpenGL開發要與一個特殊View--GLSurefaceView打交道。GLSurefaceView要使用它自己的渲染器(Render)進行圖形渲染,這個Render是運行于一個獨立的區別于主GUI線程的子線程上的。
接下來,我們跟蹤觀察一下接口Cocos2dxHelperListener的定義(它隱藏于文件Cocos2dxHelper.java中):
public static interface Cocos2dxHelperListener { public void showDialog(final String pTitle, final String pMessage); public void showEditTextDialog(final String pTitle, final String pMessage, final int pInputMode, final int pInputFlag, final int pReturnType, final int pMaxLength); public void runOnGLThread(final Runnable pRunnable); }
其中的前兩個方法與Cocos2d-x中顯然對話框與文本框有關,在此我們省略有關討論,而只專注于方法runOnGLThread。
接下來跟蹤分析,Cocos2dxActivity中定義上述方法如下:
@Override public void runOnGLThread(final Runnable pRunnable) { this.mGLSurfaceView.queueEvent(pRunnable); }
有關Runnable對象,請參考我引用的其他幾個博客文章。至于mGLSurfaceView,它是Cocos2dxGLSurfaceView類型的,而Cocos2dxGLSurfaceView是繼承自GLSurfaceView的cocos2d-x開發團隊的產品。當然,Cocos2dxGLSurfaceView內部也有一個自己的渲染器Cocos2dxRenderer,也是cocos2d-x開發團隊在類GLSurfaceView.Renderer基礎上稍微擴展的結果。
頗感遺憾的是,搜索網絡上的資源,對于queueEvent方法的解釋都不透徹。但是有幾篇還是對上面這種表達進行了一定解釋(由于本人當前沒有時間研討Android源碼,只要先借鑒網絡上看法)。說法是:GLSurfaceView的渲染線程與主GUI線程通信有多種方式,其實較為簡單的一種便是使用上面的queueEvent方法,把一個Runnable對象投擲到主線程的消息隊列中。簡言之,通過上面的方法調用,這個Runnable實現的run方法將為主GUI線程對應的Handler所檢索出并執行,從而實現了在GLSurfaceView的渲染子線程(Cocos2d-x C++這邊)中更新主GUI線程界面內容的目的。至此,文章開始處的代碼使用原因便得到解釋。
另外一句話:Cocos2d-x中的runOnGLThread相當于普通Android Java環境下的runOnUiThread方法的功能,起到子線程更新GUI主線程界面之目的。
參考文章
1.【COCOS2DX-ANDROID-游戲開發之二二】之 調用Cocos2dxGLSurfaceView (http://blog.csdn.net/teng_ontheway/article/details/17267825)。
2.Android UI thread / main thread(http://blog.csdn.net/teng_ontheway/article/details/17267557)。
3.android中的runOnUiThread(runnable)
(http://blog.csdn.net/isming/article/details/8622087)。
4.Android開發筆記之:Handler Runnable與Thread的區別詳解(http://www.jb51.net/article/37465.htm)。
5.Android的單線程模型(http://www.cnblogs.com/nio-nio/archive/2012/07/23/2604900.html)。
6.Android View.post(Runnable )(http://www.cnblogs.com/akira90/archive/2013/03/06/2946740.html)。
7.Android GLSurfaceView (http://blog.csdn.net/murongshusheng/article/details/7565771)。
8.android.opengl.GLSurfaceView概述 (http://blog.csdn.net/xqhrs232/article/details/6195824)。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。