PhoneGap插件:将JSON数据传输到本机的最快方式



我一直在开发一个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);
}

例如,如果从StringJSONArray的转换是唯一的瓶颈,那么您可以在插件中重写此方法并执行自己的反序列化。这是一个小的性能改进,但可能值得研究。

创建备用网桥

至于创建一个替代的桥梁,那就更棘手了。我对Cordova/PhoneGap了解不多,但根据我收集的研究,Cordova通过addJavascriptInterface公开了一个特定的Javascript接口。如果您能够实现自己的NativetoJSMessageQueue,那么您可能能够将其连接在一起。

编辑
在进行更多的研究后,我可以提供更多的指导。NativeoJSMessageQueue真正相关的部分是它实现的各种BridgeMode(参见第92行)。您可以以其他桥接模式为例。

不幸的是,NativetoJSMessageQueue正好注册了四种桥接模式;假设您可以实现自己的桥接模式,那么您仍然需要了解如何将其注册为NativetoJSMessageQueue的新模式。

我不确定你到底想做什么,但我注意到在你的项目中,你正在将JSON转换为String,然后你将通过PhoneGap插件将其传递,将其转换为JSON,然后转换为Matrix!

如果您将数据保存在一个字符串中,并将该字符串直接转换为矩阵,该怎么办?通过这种方式,您可以跳过到JSON部分的转换

在android上,您可以尝试使用WebViewaddJavascriptInterface(指向WebView文档的链接)方法"将Java对象注入WebView",这是PhoneGap用于添加地理位置、文件系统等API的方法。

我想这会比使用插件方法更快(还没有测试)。

检查扩展WebViewPhoneGapView的代码:https://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42

更新

毕竟,这只适用于简单类型,如intString,正如您在下面的评论中所说。

在Android 上使用addJavascriptInterface()传递JavaScript对象

否则会导致android.webkit.WebViewCoreandroid.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对象-这是一个非常有效的数据模型

最新更新