近日在用cocos2dx3.4的时候使用了JNI调用,发现一个现象
当不使用jni的时候完全正常,使用了jni后回去的所有文字都变成黑块,并且有概率程序崩溃,附带出了两个log
call to OpenGL ES API with no current context 和 Fatal signal 11
但同样的cocos2dx ,同样的jni代码,另一个项目却正常。找寻了好久之后发现了原因
cocos2dx 3.x以后版本 不再是一个进程跑到底:
引用:“Cocos2d-x从2.x版本到上周刚刚才发布的Cocos2d-x 3.0 Final版,其引擎驱动核心依旧是一个单线程的“死循环”,一旦某一帧遇到了“大活儿”,比如Size很大的纹理资源加载或网络IO或大量计算,画面将 不可避免出现卡顿以及响应迟缓的现象。从古老的Win32 GUI编程那时起,Guru们就告诉我们:别阻塞主线程(UI线程),让Worker线程去做那些“大活儿”吧。
手机游戏,即便是休闲类的小游戏,往往也涉及大量纹理资源、音视频资源、文件读写以及网络通信,处理的稍有不甚就会出现画面卡顿,交互不畅的情况。虽然引 擎在某些方面提供了一些支持,但有些时候还是自己祭出Worker线程这个法宝比较灵活,下面就以Cocos2d-x 3.0 Final版游戏初始化为例(针对Android平台),说说如何进行多线程资源加载。 我们经常看到一些手机游戏,启动之后首先会显示一个带有公司Logo的闪屏画面(Flash Screen),然后才会进入一个游戏Welcome场景,点击“开始”才正式进入游戏主场景。而这里Flash
Screen的展示环节往往在后台还会做另外一件事,那就是加载游戏的图片资源,音乐音效资源以及配置数据读取,这算是一个“障眼法”吧,目的就是提高用 户体验,这样后续场景渲染以及场景切换直接使用已经cache到内存中的数据即可,无需再行加载。”
那问题就出在cocos2dx新版本其实分了两个线程 openglview的绘制线程和程序主线程。当jni回调c++的函数中有类似sprite创建、删除、修改等,则会出现上述两个错误,导致整个内存都乱了。
再去分析了一下另一个正常项目,发现在这个项目内的jni回调中没有做任何加载图片等动作,只是更新了数据,改了文字,所以没有出现大问题。
分析可能是加载图片这类操作不能在主线程里面做,而activity直接回调jni则属于主线程,所以,解决办法也很简单,就是把回调放到openglsurfaceview中如下
class EventHandler extends Handler {
@Override
public void handleMessage(Message msg) {
{
Cocos2dxGLSurfaceView.getInstance().queueEvent(new Runnable() {
@Override
public void run() {
payResultCode(mPayId, 0);
}
});
}
}
}
核心就在这里,请大家注意一下。