Guardar matriz de objetos personalizados en estado de instancia

Tengo una List<CustomObject> (donde CustomObject viene de una biblioteca externa – no puedo hacer cambios en ella). Quiero guardar esto en onSaveInstanceState(Bundle) , pero no puedo hacerlo. Estas son las opciones que he probado:

 outState.putSerializable(KEY, (ArrayList<CustomObject>) myList); // because myList is instantiated as an ArrayList outState.putSerializable(KEY, myList.toArray()); 

Ambas opciones funcionan cuando se cambia de orientación en el teléfono (sí, onSaveInstanceState se llama al cambiar de orientación – Comprobé logcat). Sin embargo, cuando la actividad actual intenta iniciar otra (con startActivity(Intent) ), Android detiene la actividad actual y llama a onSaveInstanceState() nuevo. Esta vez, falla, por alguna razón desconocida para mí. Lo peor es que onSaveInstanceState() ejecuta correctamente. La traza de pila impresa no apunta a ninguno de mi código:

 E/AndroidRuntime(23898): java.lang.RuntimeException: Parcel: unable to marshal value my.custom.Object@5e07e43b E/AndroidRuntime(23898): at android.os.Parcel.writeValue(Parcel.java:1087) E/AndroidRuntime(23898): at android.os.Parcel.writeArray(Parcel.java:519) E/AndroidRuntime(23898): at android.os.Parcel.writeValue(Parcel.java:1072) E/AndroidRuntime(23898): at android.os.Parcel.writeMapInternal(Parcel.java:469) E/AndroidRuntime(23898): at android.os.Bundle.writeToParcel(Bundle.java:1445) E/AndroidRuntime(23898): at android.os.Parcel.writeBundle(Parcel.java:483) E/AndroidRuntime(23898): at android.app.ActivityManagerProxy.activityPaused(ActivityManagerNative.java:1427) E/AndroidRuntime(23898): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3106) E/AndroidRuntime(23898): at android.app.ActivityThread.access$2400(ActivityThread.java:119) E/AndroidRuntime(23898): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1870) E/AndroidRuntime(23898): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(23898): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime(23898): at android.app.ActivityThread.main(ActivityThread.java:4363) E/AndroidRuntime(23898): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(23898): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime(23898): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) E/AndroidRuntime(23898): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) E/AndroidRuntime(23898): at dalvik.system.NativeStart.main(Native Method) 

¿Hay alguna manera de almacenar objetos personalizados en el estado de la instancia?

Haga que su implemento Parcelable y utilice:

 outState.putParcelable(KEY, myList); onSaveInstanceState(outState); 

También compruebe este tutorial.

EDITAR después del comentario de CommonsWare:

Si su CustomObject no implementa Serializable o Parcelable intentaría envolverlo dentro de un objeto propio y añadir:

  • private void readObject(ObjectInputStream aStream) throws IOException, ClassNotFoundException { /*Your deserialization */ }
  • private void writeObject(ObjectOutputStream aStream) throws IOException { /*Your serialization */}

Haga que su List<CustomObject> sea ​​mantenida por un servicio y haga accesible a sus actividades a través del patrón de vinculación local.

No sólo no tiene que preocuparse de mantenerlo en su estado de instancia, sino que tiene un control un poco mejor sobre la vida de esos objetos en la memoria. La vida del estado de la instancia está controlada por Android; Cuánto tiempo un Service mantiene en los objetos es controlado por usted. Particularmente si CustomObject puede ser grande, o la lista puede ser larga, preferiría que tenga un mayor control sobre cuánto tiempo se consume esa RAM.

Si esto es principalmente para manejar los cambios de orientación, ¿puede Activity#onRetainNonConfigurationInstance() hacer lo que desea?

Una actividad puede utilizar esta API para propagar el estado extenso de la antigua a la nueva instancia de actividad, de mapas de bits cargados, a las conexiones de red, a los threads de ejecución activa de manera uniforme. Tenga en cuenta que no debe propagar datos que puedan cambiar en función de la configuración, incluidos los datos cargados de recursos como cadenas, diseños o dibujos.

Esta API no le ayudará si intenta hacer más que persistir datos a través de los cambios de configuración.

Por lo que sé, SavedInstanceState es para salvar la configuración de la interfaz de usuario de la actividad (como los widgets estándar de la interfaz de usuario de Android, por ejemplo, el campo de texto, se conservan automáticamente).

Si desea guardar un objeto personalizado entre diferentes relanzamientos de actividad (esto no se aplica al acabado iniciado por el usuario de una actividad haciendo clic en el botón Atrás, pero sí se aplica, por ejemplo, para cambios de orientación). Utilice el siguiente código para conservar un objeto:

 // maintain a reference to the EchoServer object when the activity is recreated @Override public Object onRetainNonConfigurationInstance() { return <<your object of choice>>; } 

Y en el método onCreate (Bundle savedInstanceState), puede recuperar el objeto:

  // if there is a saved instance state, restore the state if (savedInstanceState != null) { <<yourObject>> = (<<your object's class) getLastNonConfigurationInstance(); 

¿Por qué no sólo guardar el objeto en la tarjeta SD? Puedes ver un ejemplo de cómo uso esto en mi blog >> http://androidworkz.com/2010/07/06/source-code-imageview-flipper-sd-card-scanner/

 public void saveArray(String filename, String[] output_field) { try { FileOutputStream fos = new FileOutputStream(filename); GZIPOutputStream gzos = new GZIPOutputStream(fos); ObjectOutputStream out = new ObjectOutputStream(gzos); out.writeObject(output_field); out.flush(); out.close(); } catch (IOException e) { e.getStackTrace(); } } public String[] loadArray(String filename) { try { FileInputStream fis = new FileInputStream(filename); GZIPInputStream gzis = new GZIPInputStream(fis); ObjectInputStream in = new ObjectInputStream(gzis); String[] read_field = (String[])in.readObject(); in.close(); return read_field; } catch (Exception e) { e.getStackTrace(); } return null; } 
  • Enfoque para serializar la clase de modelo de punto final de nube en el sistema de archivos Android
  • Serialización y subclases
  • Serializar un objeto Drawable en Android
  • Orden Android Parcelable
  • Parcelable encontrado IOException writing serializable object getactivity ()
  • Guardar / cargar el estado del documento de forma rápida y robusta para el editor de imágenes
  • Java.lang.RuntimeException: Paralleable encontró IOException escribiendo objeto serializable en Android que pasa el objeto ArrayList
  • Problemas de serialización de RealmList (Realm / Gson / Intent)
  • ¿Guardando la clase en el archivo?
  • Java lanza NotSerializableException después de agregar su propia interfaz
  • Ventajas de Parcelable sobre JSON
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.