¿Cómo escribir Java.util.Map en el paquete de una manera inteligente?

Tengo un mapa genérico de cadenas (clave, valor) y este campo es parte de un Bean que tengo que ser parcelable. Por lo tanto, podría utilizar el Parcel # writeMap método. El API Doc dice:

Por favor use writeBundle (Bundle) en su lugar. Aplanar un mapa en la parcela en la posición de datos actual (), aumentando la capacidad de datos () si es necesario. Las teclas de mapa deben ser objetos String. Los valores de Map se escriben usando writeValue (Object) y deben seguir la especificación allí. Se recomienda utilizar writeBundle (Bundle) en lugar de este método, ya que la clase Bundle proporciona una API de tipo seguro que le permite evitar errores de tipo misterioso en el punto de ordenar.

Por lo tanto, podría iterar sobre cada entrada en mi mapa de ponerlo en el paquete, pero todavía estoy buscando una manera más inteligente de hacerlo. ¿Hay algún método en el SDK de Android que me falta?

Por el momento lo hago así:

final Bundle bundle = new Bundle(); final Iterator<Entry<String, String>> iter = links.entrySet().iterator(); while(iter.hasNext()) { final Entry<String, String> entry =iter.next(); bundle.putString(entry.getKey(), entry.getValue()); } parcel.writeBundle(bundle); 

Terminé haciéndolo un poco diferente. Sigue el patrón que usted esperaría para ocuparse de parcelables, así que debe ser familiar.

 public void writeToParcel(Parcel out, int flags){ out.writeInt(map.size()); for(Map.Entry<String,String> entry : map.entrySet()){ out.writeString(entry.getKey()); out.writeString(entry.getValue()); } } private MyParcelable(Parcel in){ //initialize your map before int size = in.readInt(); for(int i = 0; i < size; i++){ String key = in.readString(); String value = in.readString(); map.put(key,value); } } 

En mi solicitud, el orden de las teclas en el mapa importaba. Yo estaba usando un LinekdHashMap para preservar el orden y hacerlo de esta manera garantizado que las claves aparecerían en el mismo orden después de ser extraído de la parcela.

Si tanto la key como el value del mapa se extienden Parcelable , puede tener una solución genérica bastante genial para esto:

Código

 // For writing to a Parcel public <K extends Parcelable,V extends Parcelable> void writeParcelableMap( Parcel parcel, int flags, Map<K, V > map) { parcel.writeInt(map.size()); for(Map.Entry<K, V> e : map.entrySet()){ parcel.writeParcelable(e.getKey(), flags); parcel.writeParcelable(e.getValue(), flags); } } // For reading from a Parcel public <K extends Parcelable,V extends Parcelable> Map<K,V> readParcelableMap( Parcel parcel, Class<K> kClass, Class<V> vClass) { int size = parcel.readInt(); Map<K, V> map = new HashMap<K, V>(size); for(int i = 0; i < size; i++){ map.put(kClass.cast(parcel.readParcelable(kClass.getClassLoader())), vClass.cast(parcel.readParcelable(vClass.getClassLoader()))); } return map; } 

Uso

 // MyClass1 and MyClass2 must extend Parcelable Map<MyClass1, MyClass2> map; // Writing to a parcel writeParcelableMap(parcel, flags, map); // Reading from a parcel map = readParcelableMap(parcel, MyClass1.class, MyClass2.class); 

puedes probar:

 bundle.putSerializable(yourSerializableMap); 

Si su mapa elegido implementa serializable (como HashMap) y luego puede utilizar su writeBundle en la facilidad

Buena pregunta. No hay ningún método en la API que conozco que no sea putSerializable y writeMap. La serialización no se recomienda por razones de rendimiento, y writeMap () tampoco se recomienda por razones algo misteriosas, como ya se ha señalado.

Necesitaba parcelar un HashMap hoy, así que intenté mi mano en escribir algunos métodos de la utilidad para el mapa de la parcelación ay de un paquete de la manera recomendada:

 // Usage: // read map into a HashMap<String,Foo> links = readMap(parcel, Foo.class); // another way that lets you use a different Map implementation links = new SuperDooperMap<String, Foo>; readMap(links, parcel, Foo.class); // write map out writeMap(links, parcel); //////////////////////////////////////////////////////////////////// // Parcel methods /** * Reads a Map from a Parcel that was stored using a String array and a Bundle. * * @param in the Parcel to retrieve the map from * @param type the class used for the value objects in the map, equivalent to V.class before type erasure * @return a map containing the items retrieved from the parcel */ public static <V extends Parcelable> Map<String,V> readMap(Parcel in, Class<? extends V> type) { Map<String,V> map = new HashMap<String,V>(); if(in != null) { String[] keys = in.createStringArray(); Bundle bundle = in.readBundle(type.getClassLoader()); for(String key : keys) map.put(key, type.cast(bundle.getParcelable(key))); } return map; } /** * Reads into an existing Map from a Parcel that was stored using a String array and a Bundle. * * @param map the Map<String,V> that will receive the items from the parcel * @param in the Parcel to retrieve the map from * @param type the class used for the value objects in the map, equivalent to V.class before type erasure */ public static <V extends Parcelable> void readMap(Map<String,V> map, Parcel in, Class<V> type) { if(map != null) { map.clear(); if(in != null) { String[] keys = in.createStringArray(); Bundle bundle = in.readBundle(type.getClassLoader()); for(String key : keys) map.put(key, type.cast(bundle.getParcelable(key))); } } } /** * Writes a Map to a Parcel using a String array and a Bundle. * * @param map the Map<String,V> to store in the parcel * @param out the Parcel to store the map in */ public static void writeMap(Map<String,? extends Parcelable> map, Parcel out) { if(map != null && map.size() > 0) { /* Set<String> keySet = map.keySet(); Bundle b = new Bundle(); for(String key : keySet) b.putParcelable(key, map.get(key)); String[] array = keySet.toArray(new String[keySet.size()]); out.writeStringArray(array); out.writeBundle(b); /*/ // alternative using an entrySet, keeping output data format the same // (if you don't need to preserve the data format, you might prefer to just write the key-value pairs directly to the parcel) Bundle bundle = new Bundle(); for(Map.Entry<String, ? extends Parcelable> entry : map.entrySet()) { bundle.putParcelable(entry.getKey(), entry.getValue()); } final Set<String> keySet = map.keySet(); final String[] array = keySet.toArray(new String[keySet.size()]); out.writeStringArray(array); out.writeBundle(bundle); /**/ } else { //String[] array = Collections.<String>emptySet().toArray(new String[0]); // you can use a static instance of String[0] here instead out.writeStringArray(new String[0]); out.writeBundle(Bundle.EMPTY); } } 

Edit: modified writeMap para usar un entrySet mientras se conserva el mismo formato de datos que en mi respuesta original (mostrado en el otro lado del comentario de conmutación). Si no necesita o desea preservar la compatibilidad de lectura, puede ser más sencillo almacenar los pares clave-valor en cada iteración, como en las respuestas de @bcorso y @Anthony Naddeo.

  • Cómo utilizar writeStringArray () y readStringArray () en una parcela
  • ¿Cómo pasar el objeto Parcelable del niño a la actividad de los padres?
  • Objetivo y Parcelable objeto Android
  • ¿Cómo puedo recuperar de un paquete una secuencia de caracteres que se guardó utilizando TextUtils.writeToParcel (...)?
  • Android Parcelable - Escriba y lea ArrayList <IA> cuando IA es una interfaz
  • Cómo guardar ArrayList personalizado en la rotación de la pantalla de Android?
  • Pasar lista de objetos complejos de actividad a fragmento
  • Limitación de tamaño en adjunto ¿Parcelable?
  • Transmisión de JSONObject a otra actividad
  • ClassNotFoundException cuando unmarshalling y realmente no sé por qué
  • Crea un objeto java personalizado Parcelable en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.