溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Cocos2d-x編程中的runOnUiThread方法和runOnGLThread方法剖析

發(fā)布時間:2020-08-06 07:05:16 來源:網(wǎng)絡(luò) 閱讀:6122 作者:googlingman 欄目:游戲開發(fā)

         本文對于runOnGLThread方法的分析主要目的是為了幫助我的課程“拇指接龍游戲”學(xué)員更好地理解EasyNDK這個開源框架的使用。借助于這個框架,實現(xiàn)Android JAVA端與Cococ2d-x C++端交互,以及iOS Objective-C端與Cococ2d-x C++端交互將變得異常容易----極大地減少了相關(guān)的JNI編程與Objecive-C編程的代碼量。但是,在EasyNDK的Android版本示例中在Java主Activity端存在如下代碼段:

   
public void ChangeSomethingInCocos()
    {
        this.runOnGLThread(new Runnable()
        {
            @Override
            public void run()
            {
                AndroidNDKHelper.SendMessageWithParameters("ChangeLabelSelector", null);
            }
        });
    }

    上述代碼中SendMessageWithParameters方法為什么要運(yùn)行于runOnGLThread方法中?本文將試圖對這部分代碼進(jìn)行充分解釋。至于EasyNDK的其他部分的使用就容易理解多了。

一、回顧傳統(tǒng)Android編程中使用的runOnUiThread方法

        在android中經(jīng)常需要用到異步操作,Thread+Handler方式比較繁瑣(當(dāng)然功能也最為強(qiáng)大),而AsyncTask只能執(zhí)行一次,很多需求不能滿足(有關(guān)AsyncTask用法,請參考我引用的另外一篇博客)。

      此時,我們可以試試Activity提供的另外一種簡單的方法runOnUiThread,runOnUiThread可以幫助你在線程中執(zhí)行UI更新操作。

        以下為線程中使用runOnUiThread方法的框架代碼:

MyActivity.this. runOnUiThread(new Runnable() {   
                    @Override   
                        public void run() {   
  
                           // refresh ui 的操作代碼  
  
                        }   
                    });

    這里需要注意:runOnUiThread是Activity中的方法,在我們的工作線程中需要告訴系統(tǒng)是哪個Activity調(diào)用,所以前面顯式地指明Activity。


    下面為runOnUiThread的宏觀代碼:


public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
}

   


    從代碼可以看到,runOnUiThread首先判斷是否是UI線程,不是的話就post,如果是的話就正常運(yùn)行該線程。只要經(jīng)過主線程中的Handler.post或者postDelayed處理,線程Runnable都可以被加入到UI主線程的消息循環(huán)中,并為主線程的Handler所檢索并調(diào)用。有關(guān)的Handler運(yùn)行原理,請參考我引用的其他幾篇博客文章。


    值得注意的是,本節(jié)中的runOnUiThread方法適合于從子線程中更新普通Android View內(nèi)容時調(diào)用。但是,當(dāng)我們在Android下進(jìn)行OpenGL ES開發(fā)時,也就是本文關(guān)注的cocos2d-x開發(fā)時,需要使用另一個方法,即下文要討論的runOnGLThread。


二、Cocos2d-x編程中的runOnGLThread方法


    cocos2d-x開發(fā)中,一旦涉及到Android平臺移植自然要與Cocos2dxActivity這個東西打交道。Cocos2dxActivity是cocos2d-x開發(fā)團(tuán)隊的成果,它是一個抽象類,具體形式如下:

public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {//...}

    我們知道,cocos2d-x是運(yùn)行于OpenGL平臺的。Android平臺下進(jìn)行OpenGL開發(fā)要與一個特殊View--GLSurefaceView打交道。GLSurefaceView要使用它自己的渲染器(Render)進(jìn)行圖形渲染,這個Render是運(yùn)行于一個獨(dú)立的區(qū)別于主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中顯然對話框與文本框有關(guān),在此我們省略有關(guān)討論,而只專注于方法runOnGLThread。


    接下來跟蹤分析,Cocos2dxActivity中定義上述方法如下: 

@Override
    public void runOnGLThread(final Runnable pRunnable) {
        this.mGLSurfaceView.queueEvent(pRunnable);
    }

    有關(guān)Runnable對象,請參考我引用的其他幾個博客文章。至于mGLSurfaceView,它是Cocos2dxGLSurfaceView類型的,而Cocos2dxGLSurfaceView是繼承自GLSurfaceView的cocos2d-x開發(fā)團(tuán)隊的產(chǎn)品。當(dāng)然,Cocos2dxGLSurfaceView內(nèi)部也有一個自己的渲染器Cocos2dxRenderer,也是cocos2d-x開發(fā)團(tuán)隊在類GLSurfaceView.Renderer基礎(chǔ)上稍微擴(kuò)展的結(jié)果。


      頗感遺憾的是,搜索網(wǎng)絡(luò)上的資源,對于queueEvent方法的解釋都不透徹。但是有幾篇還是對上面這種表達(dá)進(jìn)行了一定解釋(由于本人當(dāng)前沒有時間研討Android源碼,只要先借鑒網(wǎng)絡(luò)上看法)。說法是:GLSurfaceView的渲染線程與主GUI線程通信有多種方式,其實較為簡單的一種便是使用上面的queueEvent方法,把一個Runnable對象投擲到主線程的消息隊列中。簡言之,通過上面的方法調(diào)用,這個Runnable實現(xiàn)的run方法將為主GUI線程對應(yīng)的Handler所檢索出并執(zhí)行,從而實現(xiàn)了在GLSurfaceView的渲染子線程(Cocos2d-x C++這邊)中更新主GUI線程界面內(nèi)容的目的。至此,文章開始處的代碼使用原因便得到解釋。

      另外一句話:Cocos2d-x中的runOnGLThread相當(dāng)于普通Android Java環(huán)境下的runOnUiThread方法的功能,起到子線程更新GUI主線程界面之目的。

 

參考文章


1.【COCOS2DX-ANDROID-游戲開發(fā)之二二】之 調(diào)用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開發(fā)筆記之:Handler Runnable與Thread的區(qū)別詳解(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)。

向AI問一下細(xì)節(jié)
AI