Intereting Posts
Android – вытащить Android-устройство SQlite Разница между addOnLayoutChangeListener и onLayout (изменена)? SecureRandom провайдер «Crypto» недоступен в Android N для детерминированного генерации ключа Как настроить Android ActionBar для отображения пользовательского представления перед вкладками? QGuiApplication останавливает цикл события, когда телефон блокируется при компиляции с Qt 5.3 или Qt 5.4 (но не с Qt 5.2) Как получить национальные праздники в выбранной стране Создание и запуск приложения через Gradle и Android Studio 2.0 медленнее Как создать Android Spinner в качестве всплывающего окна? Каков наилучший способ объявить компонент UI в Android с Kotlin? Android – Как сделать мультика аудиофайла и видеофайла? Xamarin.Forms untappable ListView (удаляет эффект пульсации выбора) Разница между SurfaceView и GLSurfaceView в Android Как сделать плавный переход от одного изображения к другому Spinner: onItemSelected не вызывается, когда выбранный элемент остается тем же ExpandableRecyclerAdapter Как заставить элемент перемещаться вверх при расширении элемента

Как написать Java.util.Map в пакет по разумному пути?

У меня есть общая карта строк (Key, Value), и это поле является частью Bean, который должен быть применимым. Итак, я мог бы использовать метод WriteMap для почтовых ящиков. API Doc говорит:

Вместо этого используйте writeBundle (Bundle). Сглаживает карту в посылке в текущем dataPosition (), увеличивая при этом значение dataCapacity (). Ключами карты должны быть объекты String. Значения карты записываются с использованием функции writeValue (Object) и должны следовать указанной там спецификации. Настоятельно рекомендуется использовать writeBundle (Bundle) вместо этого метода, поскольку класс Bundle предоставляет безопасный тип API, который позволяет избежать таинственных ошибок типа в точке сортировки.

Таким образом, я мог перебирать каждую запись в моей Карте, помещая ее в Bundle, но я все еще ищу более умный способ сделать это. Есть ли какой-либо метод в Android SDK, который у меня отсутствует?

На данный момент я делаю это так:

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); 

Solutions Collecting From Web of "Как написать Java.util.Map в пакет по разумному пути?"

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

 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); } } 

В моем приложении порядок ключей на карте имел значение. Я использовал LinekdHashMap, чтобы сохранить порядок, и таким образом гарантировал, что ключи будут отображаться в том же порядке после извлечения из пакета.

Если и key и value карты расширяются до Parcelable , у вас может быть довольно приятное решение Generics:

Код

 // 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; } 

Применение

 // 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); 

можешь попробовать:

 bundle.putSerializable(yourSerializableMap); 

Если ваша выбранная карта реализует сериализуемую (например, HashMap), а затем вы можете легко использовать свой writeBundle

Хороший вопрос. В API нет каких-либо методов, о которых я знаю, кроме putSerializable и writeMap. Сериализация не рекомендуется по соображениям производительности, и writeMap () также не рекомендуется по несколько таинственным причинам, как вы уже указывали.

Мне нужно было посылить HashMap сегодня, поэтому я попробовал свои силы при написании некоторых полезных методов для посылки карты в и из Bundle по рекомендованному пути:

 // 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); } } 

Изменить: изменил writeMap, чтобы использовать entrySet, сохраняя тот же формат данных, что и в моем исходном ответе (показан на другой стороне комментария переключения). Если вам не нужно или хотите сохранить совместимость с чтением, может быть проще просто хранить пары ключ-значение на каждой итерации, как в ответах @bcorso и @Anthony Naddeo.