問題場景:我們的游戲在支付時,由於第三方支付比較費時,可能在支付的過程中,我們lua寫的cocos2dx項目會斷網,我們的游戲有自動重連的機制。我就想,如果斷線好了以后,支付完成了,那在斷網之前傳入的回調函數是否能被成功執行到呢?
就在網上發現了這篇文章 http://dualface.github.io/blog/2013/01/01/call-java-from-lua/#lua20function20E79A84E5BC95E794A8E8AEA1E695B0E599A8 , 個人覺得寫的超贊。
“Lua 虛擬機中,Lua function 以值的形式保存。但這個值無法直接給 Java 用,所以 luaj 做了一個 Lua function 引用表。當一個 Lua function 傳遞給 Java 時,這個 function 對應的值會被存在引用表中,並獲得一個唯一的引用 ID (整數)。Java 代碼拿到這個引用 ID 后,就可以很方便的調用該 Lua function 了。”
“Lua 虛擬機具有自動垃圾回收機制。Lua function 既然是值,那么在沒有被使用時自然會被回收掉。所以 luaj 提供了 retainLuaFunction() 和 releaseLuaFunction() 兩個函數用於增減 Lua function 的引用計數。
將一個 Lua function 以引用 ID 的形式傳入 Java 時,luaj 會自動增加引用 ID 的計數器,所以在 Java 方法里可以放心的異步調用 Lua function。但在不需要使用該 Lua function 后,一定要調用 releaseLuaFunction() 減少該引用 ID 的計數器。當計數器為 0 時,會自動釋放該 Lua function。
如果了解 cocos2d-x 中 CCObject 的 autorelease 機制,那么對引用計數應該很熟悉,兩者是完全相同的實現機制。”
這兩段說的非常好。這樣,我就明白,即使lua短線重來回來,因為Lua虛擬機沒有重啟,那么lua function 引用表也在,並且我沒有release, 那肯定是可以回調成功的。順便這篇文章也告訴了我UI線程和GL線程一些基本知識,推薦。
貼一下我的lua代碼和java回調代碼
-- android 服務器產生訂單后 客戶端開始正式購買操作 function androidStartPay(data) if isAdroid() == false then print("不允許的平台支付") disposeLoading() payError() return end local presult = GameDataCenter:GetOrderInfo(data) local javaMethodName = "startPay" local javaParams = {presult.orderNo, presult.money, userID, userName, presult.payName, userToken, presult.productId, androidPayBack} local javaMethodSig = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" luaj.callStaticMethod(PACKAGE_NAME, javaMethodName, javaParams, javaMethodSig) end
java簡單的回調
private static void setLuaCallback(final int callback, final String result) { BaseUtils.D(TAG, "setLuaCallback ========" + result); if (callback <= 0) { BaseUtils.E(TAG, " callback is null"); return; } LuaCallback = 0; // 回調lua // s_instance.Resume(); // s_instance.onWindowFocusChanged(true); s_instance.runOnGLThread(new Runnable() { @Override public void run() { Cocos2dxLuaJavaBridge.callLuaFunctionWithString(callback, result); Cocos2dxLuaJavaBridge.releaseLuaFunction(callback); } }); }