cocos2dx中有几条线程

Android UI线程

什么是UI线程

当应用启动,系统会创建一个主线程(main thread),这个主线程负责向UI组件分发事件(包括绘制事件),也是在这个主线程里,你的应用和Android的UI组件发生交互。所以main thread也叫UI thread也即UI线程

系统不会为每个组件单独创建线程,在同一个进程里的UI组件都会在UI线程里实例化,系统对每一个组件的调用都从UI线程分发出去。响应系统回调的方法(比如响应用户动作的onKeyDown()和各种生命周期回调)永远都是在UI线程里运行。

特别的是,如果所有的工作都在UI线程,做一些比较耗时的工作比如访问网络或者数据库查询,都会阻塞UI线程,导致事件停止分发(包括绘制事件)。对于用户来说,应用看起来像是卡住了,更坏的情况是,如果UI线程blocked的时间太长(大约超过5秒),用户就会看到ANR(application not responding)的对话框。

另外,Andoid UI toolkit并不是线程安全的,所以你不能从非UI线程来操纵UI组件。你必须把所有的UI操作放在UI线程里,所以Android的单线程模型有两条原则:

  1. 不要阻塞UI线程
  2. 不要在UI线程之外访问Android UI toolkit
其他线程如何安全访问UI线程
  1. 使用Worker线程
    根据单线程模型的两条原则,首先,要保证应用的响应性,不能阻塞UI线程,所以当你的操作不是即时的那种(not instantaneous),你应该把他们放进单另的线程中。

比如点击按钮后,下载一个图片然后在ImageView中展示:

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

这段代码用新的线程来处理网络操作,但是它违反了第二条原则:
Do not access the Android UI toolkit from outside the UI thread. 从非UI线程访问UI组件会导致未定义和不能预料的行为。

  1. 为了解决这个问题,Android提供了一些方法,从其他线程访问UI线程:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
  1. 可以考虑在worker线程中使用一个Handler,来处理UI线程中传来的消息。也可以继承这个类AsyncTask 。

只有在UI线程中的对象才能操作UI线程中的对象,为了将非UI线程中的数据传送到UI线程,可以使用一个 Handler运行在UI线程中。Handler是Android framework中管理线程的部分,一个Handler对象负责接收消息然后处理消息。
你可以为一个新的线程创建一个Handler,也可以创建一个Handler然后将它和已有线程连接。如果你将一个Handler和你的UI线程连接,处理消息的代码就将会在UI线程中执行。
可以在你创建线程池的类的构造方法中实例化Handler的对象,然后用全局变量存储这个对象。
要和UI线程连接,实例化Handler的时候应该使用Handler(Looper) 这个构造方法。
这个构造方法使用了一个 Looper 对象,这是Android系统中线程管理的framework的另一个部分。
当你用一个特定的 Looper实例来创建一个 Handler时,这个 Handler就运行在这个 Looper的线程中。
在Handler中,要覆写handleMessage() 方法。Android系统会在Handler管理的相应线程收到新消息时调用这个方法。

UGL线程

cocos2d-x 在 Android 平台上存在两个线程,分别是 GL 线程(负责图像渲染) UI 线程(负责 Android 系统用户界面)

在 cocos2d-x 启动后,Lua/C++代码将由 GL 线程调用,因此从 Lua/C++中调用的 Java 方法如果涉及到系统用户界面的显示、更新操作,那么就必须让这部分代码切换到 UI 线程上去运行。

反之亦然,从 Java 调用 Lua/C++代码时,需要让这个调用在 GL 线程上执行,否则 Lua/C++代码虽然执行了,但会无法更新 cocos2d-x 内部状态。
确保 Lua/C++function 跑在 GL 线程,Java 代码跑在 UI 线程

在接入支付SDK的过程,任何的支付SDK都会自带有支付的界面,这个时候就涉及到我们的UI刷新了,如果你不小心直接通过JNI调的函数来调用支付界面的话,轻则无响应,重则直接挂了

1:cocos2dx是如何实现跨平台的

Cocos2dx基于opengl es 实现跨平台工程

Android程序在启动的时候,首先加载了我们的MainActivity,这个时候Java加载了c++平台编译的.so文件。然后我们在根据Activity的声明周期走起来~

public void init() {
        // FrameLayout
        ViewGroup.LayoutParams framelayout_params =
            new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                       ViewGroup.LayoutParams.FILL_PARENT);
        FrameLayout framelayout = new FrameLayout(this);
        framelayout.setLayoutParams(framelayout_params);

        // Cocos2dxEditText layout

        ViewGroup.LayoutParams edittext_layout_params =
            new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                       ViewGroup.LayoutParams.WRAP_CONTENT);
        Cocos2dxEditText edittext = new Cocos2dxEditText(this);
        edittext.setLayoutParams(edittext_layout_params);
        // ...add to FrameLayout
        framelayout.addView(edittext);
        // Cocos2dxGLSurfaceView
        this.mGLSurfaceView = this.onCreateView();
        // ...add to FrameLayout
        framelayout.addView(this.mGLSurfaceView);
        // Switch to supported OpenGL (ARGB888) mode on emulator
        if (isAndroidEmulator())
           this.mGLSurfaceView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
        this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
        this.mGLSurfaceView.setCocos2dxEditText(edittext);
        // Set framelayout as the content view
        setContentView(framelayout);
    }

主要基于GLSurfaceView,将GLSurfaceView添加到我们的视图中。设置了renderer去调起了GLSurfaceView的onSurfaceCreated()

public void onSurfaceCreated(final GL10 pGL10, final EGLConfig pEGLConfig) {
        Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);
        this.mLastTickInNanoSeconds = System.nanoTime();
    }

这行代码就很清晰了,通过native方法去调用我们的cocos2dx的初始化入口函数。

bool MainLayer::init(){
    CCLayer::init();
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//通知Android显示dialog
        CallJava::onShowDialog();
    #endif
}

这里是cocos2dx的C++代码,在初始化页面的时候调用Android的dialog框

public static void onShowDialog(){
        runrun.getInstance().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                AlertDialog dialog = new AlertDialog.Builder(runrun.getInstance()).create();
                dialog.setTitle("cocos2dx:");
                dialog.setMessage("Android");
                dialog.setCancelable(false);
                dialog.show();
            }
        });
    }

这里,我们需要先切换到UI线程来,再show出我们的dialog

Android---->Cocos2dx

activity.runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    Log.e("--->", "Untils_  "+Thread.currentThread().getName());
                    CallCpp.getItem(id);
                }
            });

这里切换到GLSurfaceView的线程,刷新了UI。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章