Эффективный способ получить данные JSON для носимых устройств

Я пытаюсь прочитать канал с URL-адреса в виде объекта JSON и передать этот канал на носимое устройство для отображения в виде списка с помощью API данных. Этот объект JSON содержит массив объектов, каждый из которых содержит несколько элементов. Что-то вроде этого:

{ "items":[
    { "title":"item 1", "element_1":"element 1", "element_2":"element 2" }
    { "title":"item 2", "element_1":"element 1", "element_2":"element 2" }
    { "title":"item 3", "element_1":"element 1", "element_2":"element 2" }
]}

Я могу поместить эти предметы в ArrayList объектов с помощью GSON или Jackson (хотя я думаю, что предпочитаю GSON), но я не знаю, как я смогу преобразовать эти ArrayList объектов в носимые устройства. Из того, что я могу сказать, я не могу. Я хотел бы знать, есть ли способ сделать это, или, если нет, какие-то передовые методы того, как мне это сделать? Должен ли я просто получить JSON в виде строки, передать строку на носимое устройство и затем проанализировать ее? Я не знаю, было бы это неэффективно, если бы строка была очень большой, учитывая, что я не знаю, насколько большим может быть список объектов JSON. Также я знаю, что можно разобрать строку с помощью GSON, но я не знаю, неэффективно ли это.


person Bryan    schedule 29.10.2015    source источник
comment
Должны ли носимые устройства получать полный список предметов или только их часть?   -  person dragi    schedule 29.10.2015
comment
@helleye Да, полный список предметов.   -  person Bryan    schedule 29.10.2015
comment
Вы отправляете данные в виде сообщений и отправляете как сообщения с помощью MessageApi< /а>   -  person krishnan    schedule 29.10.2015
comment
@krishnan Я думаю, что в моем случае это было бы очень неэффективно, учитывая, что некоторые элементы в массиве JSON будут статичными в течение определенного периода времени. Насколько я понимаю, DataApi может хранить эти данные, чтобы носимое устройство извлекало больше данных только при обновлении списка. Способ, которым я в настоящее время достигаю этого, заключается в том, чтобы носимое устройство отправляло сообщение на портативное устройство для обновления данных при его открытии, а затем носимое прослушивало это обновление. Если данные не изменились, нагрузка на носимое устройство отсутствует. Если я постоянно отправляю сообщения, то носимое устройство постоянно использует драгоценные ресурсы.   -  person Bryan    schedule 29.10.2015


Ответы (2)


Общие рекомендации заключаются в том, чтобы отправлять на носимые устройства минимум данных, которые ему необходимы, и выполнять максимальную обработку данных на портативном устройстве, так как оно имеет гораздо большую вычислительную мощность (и батарею). ).
Согласно документации: https://developers.google.com/android/reference/com/google/android/gms/wearable/DataItem.html#setData(byte[])
Текущий максимальный размер элемента данных составляет приблизительно 100 КБ. Элементы данных, как правило, должны быть намного меньше этого ограничения.
Вы должны принять решение, если это соответствует вашим потребностям. Если возможно получить очень большой JSON, возможно, вы можете разделить его на стороне портативного устройства, или вы можете отфильтровать некоторые данные внутри.

Если вы считаете, что это невозможно для вашего случая, то, возможно, вам следует пересмотреть свои требования!


Я обрабатываю JSON с помощью GSON непосредственно на носимом устройстве, и для моих вариантов использования он работает достаточно хорошо.

person dragi    schedule 29.10.2015
comment
вы отправляете его с помощью MessageClient или с чем-то еще? - person pushandpop; 16.03.2019
comment
@pushandpop К сожалению, я не помню, что использовал, у меня нет доступа к этому исходному коду, и я больше не занимаюсь разработкой для Android :) - person dragi; 18.03.2019

Я нашел пример Android Wear XYZTouristAttractions, и это мой текущий код, основанный на этом пример. Во-первых, я создал общую библиотеку, чтобы уменьшить дублирование кода. Эта общая библиотека содержит класс Item, содержащий данные JSON. Я использую этот класс в моем DownloadArrayListTask на КПК, который берет объект JSON из входного потока и помещает данные в ArrayList из Item объектов.

@Override
protected ArrayList<Item> doInBackground(URL... params) {
    URL url = params[0];
    ArrayList<Item> items = new ArrayList<>();

    try {
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        try {
            InputStreamReader input = new InputStreamReader(connection.getInputStream());

            Type listType = new TypeToken<Map<String, ArrayList<Item>>>(){}.getType();
            Gson gson = new GsonBuilder().create();
            Map<String, ArrayList<Item>> treeMap = gson.fromJson(input, listType);
            items = treeeMap.get("items");

            input.close();
        } finally {
            connection.disconnect();
        }
    } catch (IOException exception) {
        exception.printStackTrace();
    }

    return items
}

Эти ArrayList разбиваются на цепочки в DataLayerListenerService и помещаются в ArrayList из DataMap объектов для приема носимыми устройствами.

@Override
public void onMessageReceived(MessageEvent messageEvent) {
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API).build();

    ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
    if(!connectionResult.isSuccess()) {
        Log.e(TAG, "Failed to connect to Google API Client");
        return;
    }

    if(messageEvent.getPath().equals("/update_path") {
        ArrayList<Item> items = new ArrayList<>()
        try {
            items = new DownloadArrayListTask().execute(new URL("http://my_url")).get();
        } catch (MalformedURLException | InterruptedException | ExecutionException exception) {
            exception.printStackTrace();
        }

        ArrayList<DataMap> itemMaps = new ArrayList<>(items.size());

        for(Item item : items) {
            DataMap dataMap = new DataMap();
            dataMap.putString("title", item.getTitle());
            dataMap.putString("element1", item.getElement1());
            dataMap.putString("element2", item.getElement2());

            itemMaps.add(dataMap);
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await();

                for(Node node : nodes.getNodes()) {
                    PutDataMapRequest dataMapRequest = PutDataMapRequest.create("/item_path");
                    dataMapRequest.getDataMap().putDataMapArrayList("item_key", itemMaps);

                    PutDataRequest request = dataMapRequest.asPutDataRequest();
                    DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await();

                    if(!result.getStatus().isSuccess()) {
                        Log.d(TAG, "Failed to send data");
                    }
                } 
            }
        }).start();
    }
}

Затем носимое устройство получает эти ArrayList из DataMap объектов и использует свои собственные AsyncTask, чтобы поместить их обратно в ArrayList из Item объектов.

@Override
protected ArrayList<Item> doInBackground(Uri... params) {
    Uri uri = params[0];
    ArrayList<Item> items = new ArrayList<>();

    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API).build();

    ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
    if(!connectionResult.isSuccess()) {
        Log.e(TAG, "Failed to connect to Google API Client");
        return;
    }

    DataItemBuffer results = Wearable.DataApi.getDataItems(googleApiClient).await();

    if(results.getStatus().isSuccess() && results.getCount() != 0) {
        DataMapItem dataMapItem = DataMapItem.fromDataItem(results.get(0);

        List<DataMap> data = dataMapItem.getDataMap().getDataMapArrayList("item_key");

        for(DataMap dataItem : data) {
            Item item = new Item(dataItem.getString("title"),
                    dataItem.getString("element1"),
                    dataItem.getString("element2"));
            items.add(item);
        }
    } else {
        Log.d(TAG, "Failed to obtain data");
    } return items;
}
person Bryan    schedule 04.11.2015
comment
Эй, побочный вопрос. Что вы делаете с этими вещами потом (при носке)? Вы храните их в локальной базе данных или каким-то образом заставляете их повторно доставляться с портативного устройства при следующем запуске приложения Wear? - person Dennis K; 13.11.2015
comment
@DennisK В настоящее время я отправляю сообщение на КПК каждый раз, когда приложение запускается, чтобы повторно синхронизировать данные. Я не пытался сохранять в локальную базу данных, потому что информация, которую я получаю, актуальна только в том случае, если она актуальна. Вы должны иметь возможность сохранить его в локальной базе данных на носимом устройстве, хотя я не знаком с ограничениями платформы износа. - person Bryan; 13.11.2015