2011-03-29 9 views
5

Tengo una aplicación de servidor/cliente donde recupero datos del servidor a través de Hessian/hessdroid. Los datos son muy complejos con HashMaps que contienen otros HashMaps e imágenes almacenadas en matrices de bytes. Puedo mostrar los datos perfectamente.De-serialización de HashMap

Para no consultar siempre el servidor, estoy usando una estructura de datos como caché. Este objeto de datos lo guardo en la tarjeta SD usando ObjectOutputStream al cerrar la aplicación. Cuando lo reinicio, lo leo de vuelta a la memoria con un ObjectInputStream.

Tengo problemas con la aplicación solo después de leer los datos de la tarjeta SD. LogCat me da la siguiente salida (100 veces):

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

y esto en medio de los otros mensajes:

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

Cuando el montón crece sobre ~ 17 MB la aplicación se bloquea.

He leído varios hilos sobre la serialización HashMap y que parece haber un error al serializar entre arquitecturas, pero para mí la transferencia de datos a través de Hessian funciona perfectamente y tengo los problemas descritos solo cuando leo los HashMaps desde el disco.

¿Alguna idea?

+0

¿Podría publicar el código donde carga y deserializa los datos? –

+0

Agregue un volcado completo de log cat y el código fuente mencionado por el Sr. Earl. De lo que dijiste aquí huele más como un problema de falta de memoria (quizás esto ayudará a http://code.google.com/p/android/issues/detail?id=14869). –

Respuesta

2

El problema no está directamente relacionado con la deserialización de HashMap, como comentó cyber-monk. De hecho, hay algún tipo de error en Android o su implementación de HashMap, pero no creo que sea por eso que la aplicación falla.

Por ahora he resuelto el problema, usando menos imágenes en la aplicación. Tenía una galería, por ejemplo, en la que podía deslizar de una imagen a la siguiente en una aleta y cargar todas las imágenes a la vez. En una cierta cantidad de imágenes, no hay suficiente espacio en el montón.

Mi solución a esto es no mantener todas las imágenes decodificadas a la vez.

Está hecho de esta manera:

1) Mantenga los datos binarios de imagen en la memoria (no es un problema siempre y cuando las imágenes no son tan grandes)

2) ¡No cargar el binario datos de imagen en las ImageViews al crear las vistas de la aleta.

3) Establezca los datos de imagen binaria en el ImageView que se muestra.

4) mantener los datos de imagen binaria de la siguiente y la última ImageView para una mejor experiencia de usuario)

5) "Descargar" ImageViews los que no se visualizan mediante el establecimiento de sus recursos para el color transparente.

tope aquí tienes algo de código:

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

RenderView() sólo devuelve un LinearLayout que contiene un ImageView

Entonces escribí algunos métodos para mostrar la imagen siguiente/anterior en la cual di los datos binarios a la 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); 
    } 
} 

para mejorar el manejo de la memoria furtherly Estoy utilizando un código en la clase BitmapHelper que he encontrado en stackoverflow, que ayuda a ahorrar memoria para imágenes reduciendo su tamaño.