我一直在开发一个PhoneGap插件,以启用WebGL,用于将HTML5游戏发布到手机上。它被称为WebGLGap。然而,PhoneGap调用插件代码的方式(通过exec)通常包括将所有参数字符串化为JSON,然后在另一端再次解析它。根据这个问题,即使在PhoneGap 2.2中,这一点也没有改变,它被宣传为具有更快的桥接器。对于像WebGL这样的东西来说,这是绝对站不住脚的,甚至对于简单的演示来说也会影响性能(<10 FPS)。这是因为在许多情况下,尤其是2D游戏中,每一帧都必须传输一大块JSON数据,表示要运行的所有WebGL命令。这包括所有顶点数据——想象一下每帧都有一个巨大的字符串"0.959455、0.959595、0.588575、0.585858……"。
显然,字符串化和解析是一个不必要且效率低下的步骤,但我正在努力寻找一种方法,将JSON数据从JS传递到本机,从而避免这种情况。理想情况下,这应该在Android和iOS上都适用,但我很高兴现在坚持使用仅限Android的解决方案。有人知道最有效的方法吗?
Linkedin在iPad应用程序中使用Web套接字。可能值得研究:http://engineering.linkedin.com/mobile/linkedin-ipad-nativeweb-messaging-bridge-and-websockets
你正在寻找的一些好处
- WebSockets可以从JavaScript异步通信到本机
- WebSockets没有负载限制
- WebSockets不需要我们将JSON字符串编码为URL参数
- WebSockets应该比URL方案导航更快
寻址性能
查看CordovaPlugin.java,正如您所提到的,一切都是String
:
public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
JSONArray args = new JSONArray(rawArgs);
return execute(action, args, callbackContext);
}
例如,如果从String
到JSONArray
的转换是唯一的瓶颈,那么您可以在插件中重写此方法并执行自己的反序列化。这是一个小的性能改进,但可能值得研究。
创建备用网桥
至于创建一个替代的桥梁,那就更棘手了。我对Cordova/PhoneGap了解不多,但根据我收集的研究,Cordova通过addJavascriptInterface
公开了一个特定的Javascript接口。如果您能够实现自己的NativetoJSMessageQueue
,那么您可能能够将其连接在一起。
编辑
在进行更多的研究后,我可以提供更多的指导。NativeoJSMessageQueue真正相关的部分是它实现的各种BridgeMode(参见第92行)。您可以以其他桥接模式为例。
不幸的是,NativetoJSMessageQueue
正好注册了四种桥接模式;假设您可以实现自己的桥接模式,那么您仍然需要了解如何将其注册为NativetoJSMessageQueue
的新模式。
我不确定你到底想做什么,但我注意到在你的项目中,你正在将JSON转换为String,然后你将通过PhoneGap插件将其传递,将其转换为JSON,然后转换为Matrix!
如果您将数据保存在一个字符串中,并将该字符串直接转换为矩阵,该怎么办?通过这种方式,您可以跳过到JSON部分的转换
在android上,您可以尝试使用WebView
的addJavascriptInterface
(指向WebView文档的链接)方法"将Java对象注入WebView",这是PhoneGap用于添加地理位置、文件系统等API的方法。
我想这会比使用插件方法更快(还没有测试)。
检查扩展WebView
的PhoneGapView
的代码:https://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42
更新
毕竟,这只适用于简单类型,如int
或String
,正如您在下面的评论中所说。
在Android 上使用addJavascriptInterface()传递JavaScript对象
否则会导致android.webkit.WebViewCore
和android.webkit.JWebCoreJavaBridge
类中出现异常。
更新2
好吧,使用这种方法将获得的最佳代码是这样的(来自https://github.com/commonsguy/cw-advandroid/blob/master/WebView/GeoWeb1/src/com/commonsware/android/geoweb/GeoWebOne.java#L80):
public String getLocation() throws JSONException {
Location loc=myLocationManager.getLastKnownLocation(PROVIDER);
if (loc==null) {
return(null);
}
JSONObject json=new JSONObject();
json.put("lat", loc.getLatitude());
json.put("lon", loc.getLongitude());
return(json.toString());
}
最有可能的是,所有参数都应该字符串化(或JSON化…)
如果您在尝试从javascript端创建字符串时遇到性能问题,这可能会对您有所帮助:http://www.javascripture.com/ArrayBuffer
我读过关于用png编码数据的文章。以下是原文:http://cg.alexandra.dk/2012/11/26/webgl-tutorial-optimizing-data-transfer-for-webgl-applications/
可能有用。
鉴于json的效率非常低,如果您采用以下路线,您可能会获得很多性能:
服务器端:数据模型->protobuf(build()到二进制)->编码base64(二进制到字符串)->添加为一个json字段或有效载荷(最好是将二进制blob作为有效载荷传递,但我不确定PhoneGap是否允许)
客户端:从base64解码(字符串到二进制)->protobuf(从二进制解析)->在代码中尽可能深入地直接使用protobuf对象-这是一个非常有效的数据模型