Плагин 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 в native, что позволяет избежать этого. В идеале это должно работать как на Android, так и на iOS, но я счастлив придерживаться только Android-решения. Есть ли у кого-нибудь идеи относительно наиболее эффективного способа сделать это?
Ответы
Ответ 1
Linkedin использует веб-сокеты для своего iPad-приложения. Можно подумать: http://engineering.linkedin.com/mobile/linkedin-ipad-nativeweb-messaging-bridge-and-websockets
Некоторые преимущества, которые вы ищете
- WebSockets может связываться асинхронно с JavaScript на native.
- У WebSockets нет предела полезной нагрузки
- WebSockets не требуют, чтобы мы кодировали наши строки JSON в качестве параметров URL
- WebSockets должен быть быстрее навигации по схеме URL.
Ответ 2
Производительность адресации
Глядя на 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, но из каких исследований я собрал Кордова предоставляет конкретный интерфейс Javascript через addJavascriptInterface
. Если вы можете реализовать свой собственный NativetoJSMessageQueue
, вы можете связать все это вместе.
ИЗМЕНИТЬ
Проведя немного больше исследований, я могу дать немного больше направлений. На самом деле актуальная часть NativetoJSMessageQueue представляет собой различные BridgeModes, которые она реализует (см. line 92). В качестве примера вы можете посмотреть другие режимы моста.
К сожалению, NativetoJSMessageQueue
имеет ровно четыре зарегистрированных режима моста; предполагая, что вы можете реализовать свой собственный режим моста, вам все равно нужно каким-то образом зарегистрировать его как новый режим для NativetoJSMessageQueue
.
Ответ 3
Я не уверен, что именно вы хотите сделать, но я заметил, что в вашем проекте вы конвертируете JSON в String, а затем передаете его через плагин PhoneGap, конвертируете его в JSON, а затем конвертируете в Matrix!
что, если вы сохраните свои данные в строке и преобразуете строку прямо в матрицу?
таким образом вы можете пропустить преобразование в часть JSON и из нее
Ответ 4
В андроиде вы можете попробовать использовать addJavascriptInterface
(ссылка на документацию WebView) метод WebView
to "ввести Java-объекты в WebView", который является подходом, который использует PhoneGap для добавления apis для геолокации, файловой системы и т.д.
Я предполагаю, что это будет быстрее, чем использование подхода плагина (еще не проверили это).
Проверьте код PhoneGapView
, который расширяет WebView
:
https://github.com/phonegap/phonegap/blob/3c7324ea8b3944b6e5d3d91e9e328c9c3939464b/android/framework/src/com/phonegap/PhoneGapView.java#L42
UPDATE
В конце концов, это работает только для простых типов, таких как int
или String
, как вы сказали в комментарии ниже.
Передача объекта JavaScript с помощью addJavascriptInterface() на Android
Попытка сделать иначе приведет к исключениям из классов 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());
}
и, скорее всего, все параметры должны быть string'fied (или JSON'fied...)
Это может помочь вам, если у вас есть производительность, когда triying создает строки со стороны javascript: http://www.javascripture.com/ArrayBuffer
Ответ 5
Я читал о данных кодирования в png. Вот оригинальная статья: http://cg.alexandra.dk/2012/11/26/webgl-tutorial-optimizing-data-transfer-for-webgl-applications/
Может быть полезно.
Ответ 6
Учитывая, что json очень неэффективен, вы можете получить большую производительность, если вы выполните этот маршрут:
сторона сервера:
data model → protobuf (build() to binary) → encode base64 (двоичный код для строки) → добавить как одно поле json или полезную нагрузку (лучше всего передать бинарный блок как полезную нагрузку, но я не уверен, что PhoneGap разрешает это)
клиентская сторона:
декодировать из base64 (строка в двоичный) → protobuf (проанализировать из двоичного) → использовать объекты protobuf как можно глубже, чем вы можете в своем коде - это чрезвычайно эффективная модель данных