cocos2dx Jni呼叫需要執行緒切換 ui執行緒和GL執行緒
cocos2d-x for Android 執行在多執行緒環境下,所以在 Lua/C++ 和 Java 互動時需要注意選擇適當的執行緒。
cocos2d-x 在 Android 上以兩個執行緒來執行,分別是負責影象渲染的 GL 執行緒和負責 Android 系統使用者介面的 UI 執行緒。
- 在 cocos2d-x 啟動後,Lua/C++程式碼將由 GL 執行緒呼叫,因此從 Lua/C++中呼叫的 Java 方法如果涉及到系統使用者介面的顯示、更新操作,那麼就必須讓這部分程式碼切換到 UI 執行緒上去執行。
- 反之亦然,從 Java 呼叫 Lua/C++程式碼時,需要讓這個呼叫在 GL 執行緒上執行,否則 Lua/C++程式碼雖然執行了,但會無法更新 cocos2d-x 內部狀態。
確保 Lua/C++function 跑在 GL 執行緒,Java 程式碼跑在 UI 執行緒。
簡單說說,我相信每個人做Android的都知道的更新UI只能在UI執行緒進行重新整理,這是一個非常霸道的條款
而且,我們的UI執行緒不能被阻塞。
在接入支付SDK的過程,任何的支付SDK都會自帶有支付的介面,這個時候就涉及到我們的UI重新整理了,如果你不小心直接通過JNI調的函式來
呼叫支付介面的話,輕則無響應,重則直接掛了,hhh~~
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。