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

简介:

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

    
1
2
3
4
5
6
7
8
9
10
11
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方法的框架代码:

1
2
3
4
5
6
7
8
MyActivity. this . runOnUiThread( new  Runnable() {   
                     @Override   
                         public  void  run() {   
   
                            // refresh ui 的操作代码  
   
                         }   
                     });

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


    下面为runOnUiThread的宏观代码:


1
2
3
4
5
6
7
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开发团队的成果,它是一个抽象类,具体形式如下:

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

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


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

1
2
3
4
5
     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中定义上述方法如下: 

1
2
3
4
@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)。



















本文转自朱先忠老师51CTO博客,原文链接: http://blog.51cto.com/zhuxianzhong/1592128,如需转载请自行联系原作者


相关文章
|
5月前
|
程序员 Linux C语言
程序员必知:如何用cocos2d
程序员必知:如何用cocos2d
29 2
|
JavaScript Android开发 C++
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
【Cocos2d-x】开发基础-第一个Cocos2d-x游戏
229 0
|
iOS开发 C++
《Cocos2D-x权威指南》——第3章 Cocos2D-x中的核心类
本节书摘来自华章计算机《Cocos2D-x权威指南》一书中的第3章,作者:满硕泉著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
914 0