1. 程式人生 > >cocos2dx Jni呼叫需要執行緒切換 ui執行緒和GL執行緒

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。