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

前端之家收集整理的这篇文章主要介绍了Cocos2d-x编程中的runOnUiThread方法和runOnGLThread方法剖析前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本文对于runOnGLThread方法的分析主要目的是为了帮助我的课程“拇指接龙游戏”学员更好地理解EasyNDK这个开源框架的使用。借助于这个框架,实现Android JAVA端与Cococ2d-x C++端交互,以及iOS Objective-C端与Cococ2d-x C++端交互将变得异常容易----极大地减少了相关的JNI编程与Objecive-C编程的代码量。但是,在EasyNDK的Android版本示例中在Java主Activity端存在如下代码段:


publicvoidChangeSomethingInCocos()
{
this.runOnGLThread(newRunnable()
{
@Override
publicvoidrun()
{
AndroidNDKHelper.SendMessageWithParameters("ChangeLabelSelector",null);
}
});
}

上述代码中SendMessageWithParameters方法为什么要运行于runOnGLThread方法中?本文将试图对这部分代码进行充分解释。至于EasyNDK的其他部分的使用就容易理解多了。

一、回顾传统Android编程中使用的runOnUiThread方法

在android中经常需要用到异步操作,Thread+Handler方式比较繁琐(当然功能也最为强大),而AsyncTask只能执行一次,很多需求不能满足(有关AsyncTask用法,请参考我引用的另外一篇博客)。

此时,我们可以试试Activity提供的另外一种简单的方法runOnUiThread,runOnUiThread可以帮助你在线程中执行UI更新操作。

以下为线程中使用runOnUiThread方法的框架代码

MyActivity.this.runOnUiThread(newRunnable(){
@Override
publicvoidrun(){

//refreshui的操作代码

}
});

这里需要注意:runOnUiThread是Activity中的方法,在我们的工作线程中需要告诉系统是哪个Activity调用,所以前面显式地指明Activity。


下面为runOnUiThread的宏观代码:


publicfinalvoidrunOnUiThread(Runnableaction){
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开发团队的成果,它是一个抽象类,具体形式如下:

publicabstractclassCocos2dxActivityextendsActivityimplementsCocos2dxHelperListener{//...}

我们知道,cocos2d-x是运行于OpenGL平台的。Android平台下进行OpenGL开发要与一个特殊View--GLSurefaceView打交道。GLSurefaceView要使用它自己的渲染器(Render)进行图形渲染,这个Render是运行于一个独立的区别于主GUI线程的子线程上的。


接下来,我们跟踪观察一下接口Cocos2dxHelperListener的定义(它隐藏于文件Cocos2dxHelper.java中):

publicstaticinterfaceCocos2dxHelperListener{
publicvoidshowDialog(finalStringpTitle,finalStringpMessage);
publicvoidshowEditTextDialog(finalStringpTitle,finalStringpMessage,finalintpInputMode,finalintpInputFlag,finalintpReturnType,finalintpMaxLength);
publicvoidrunOnGLThread(finalRunnablepRunnable);
}

其中的前两个方法与Cocos2d-x中显然对话框与文本框有关,在此我们省略有关讨论,而只专注于方法runOnGLThread


接下来跟踪分析,Cocos2dxActivity中定义上述方法如下:

@Override
publicvoidrunOnGLThread(finalRunnablepRunnable){
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)。

猜你在找的Cocos2d-x相关文章