Десериализация HashMap - PullRequest
5 голосов
/ 29 марта 2011

У меня есть приложение сервер / клиент, где я получаю данные с сервера через Hessian / hessdroid.Данные очень сложны, поскольку HashMaps содержат другие HashMaps и изображения, хранящиеся в байтовых массивах.Я могу отображать данные идеально.

Чтобы не всегда запрашивать сервер, я использую структуру данных в качестве кэша.Этот объект данных я сохраняю на SD-карту, используя ObjectOutputStream при закрытии приложения.Когда я перезапускаю его, я считываю его обратно в память с помощью ObjectInputStream.

У меня проблемы с приложением только после чтения данных с SD-карты.LogCat дает мне следующий вывод (100 раз):

DEBUG/dalvikvm(4150): GetFieldID: unable to find field Ljava/util/HashMap;.loadFactor:F

и это между другими сообщениями:

INFO/dalvikvm-heap(4150): Grow heap (frag case) to 10.775MB for 281173-byte allocation

Когда размер кучи увеличивается после ~ 17 МБ, приложение вылетает.

Я прочитал несколько веток о сериализации HashMap и, похоже, что при сериализации между архитектурами возникает ошибка, но для меня передача данных через Hessian работает отлично, и у меня возникают описанные проблемы только при чтении HashMaps с диска.

Есть идеи?

1 Ответ

2 голосов
/ 26 мая 2011

Проблема не связана напрямую с десериализацией HashMap, как прокомментировал кибер-монах.Действительно, в Android или в реализации HashMap есть какая-то ошибка, но я не думаю, что именно поэтому происходит сбой приложения.

К настоящему времени я решил эту проблему, используя меньше изображений в приложении.Например, у меня была галерея, в которой вы можете перемещаться от одного изображения к другому во флиппере и загружать все изображения одновременно.При определенном количестве изображений недостаточно места в куче.

Мое решение состоит в том, чтобы не сохранять все декодированные изображения сразу.

Это сделано так:

1) Храните двоичные данные изображения в памяти (не проблема, если изображения не такие большие)

2) Не загружайте двоичные данные изображения в ImageViews при созданиивиды ласта.

3) Установите данные двоичного изображения в отображаемом ImageView.

4) Сохраните данные двоичного изображения следующего и последнего ImageView для лучшего взаимодействия с пользователем)

5) «Выгрузить» изображения, которые не отображаются, установив для своего ресурса прозрачный цвет.

Вот некоторый код:

// initialize the viewFlipper by creating blank views
for (ComponentImageDto listElement : images) {
    LinearLayout view = renderView();
    flipper.addView(view);
}
showImage(flipper.getCurrentView());

renderView ()просто возвращает LinearLayout, содержащий ImageView

Затем я написал несколько методов для отображения следующего / предыдущего изображения, в котором я установил двоичные данные для ImageView:

private void showNextElement() {
    // show next flipper view
    flipper.showNext();

    // get current view
    int displayedChild = flipper.getDisplayedChild();
    View currentView = flipper.getCurrentView();

    // load the binary data
    showImage(currentView);

    // get the next to last view index (if keeping max. 3 images at a time in memory)
    int otherChild = (displayedChild - 2);
    if (otherChild < 0) {
        otherChild = otherChild + flipper.getChildCount();
    }

    // .. and remove it
    removeImage(flipper.getChildAt(otherChild));
}

private void showPreviousElement() {
    flipper.showPrevious();
    int displayedChild = flipper.getDisplayedChild();
    View currentView = flipper.getCurrentView();
    showImage(currentView);
    setTitle((CharSequence) currentView.getTag());
    int otherChild = (displayedChild + 2) % flipper.getChildCount();
    removeImage(flipper.getChildAt(otherChild));
}

private void removeImage(View view) {
    ImageView imageView = (ImageView) view.findViewById(R.id.gallery_image);
    if (imageView != null) {
        imageView.setImageResource(R.color.transparent);
        System.gc();
    }
}

private void showImage(View view) {
    ImageView imageView = (ImageView) view.findViewById(R.id.gallery_image);
    if (imageView != null) {
        bm = BitmapHelper.decodeByteArray(images.get(flipper.getDisplayedChild()).getImage().getBinaryObject());
        imageView.setImageBitmap(bm);
    }
}

Для дальнейшего улучшения обработки памятиЯ использую какой-то кодв классе BitmapHelper, который я нашел в stackoverflow, который помогает экономить память для изображений за счет уменьшения их размера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...