Android HashMap в комплекте?

91

android.os.MessageИспользует Bundleдля отправки с его SendMessage-методом. Следовательно, можно ли поместить HashMapвнутрь a Bundle?

Маркус Топпер
источник
java И android новичок 8) спасибо всем!
Marcus Toepper
Примите любой ответ, если мы решим вашу проблему. thx
AMerle
возможный дубликат Android - как передать HashMap <String, String> между действиями?
Андре Боссард

Ответы:

165

попробуйте как:

Bundle extras = new Bundle();
extras.putSerializable("HashMap",hashMap);
intent.putExtras(extras);

и во втором действии

Bundle bundle = this.getIntent().getExtras();

if(bundle != null) {
   hashMap = bundle.getSerializable("HashMap");
}

потому что Hashmap по умолчанию реализует, Serializableпоэтому вы можете передать его, используя putSerializableв Bundle, и перейти к другим действиям, используяgetSerializable

ρяσѕρєя К
источник
Я получаю сообщение об ошибке при попытке сериализовать связанную хеш-карту Parcel: не удалось упорядочить значение com.SGID.DataClass.InvalidSubscriptionReasonsData@41bd2b98
SweetWisher ツ
1
Могу ли я использовать этот метод для объекта, который содержит примитивный тип данных и список массивов другого объекта?
SweetWisher ツ
3
Если у вас возникли проблемы, убедитесь, что вы используете HashMap, а не Map
Мэтью,
1
вы можете преобразовать возвращенный сериализуемый объект в hashmap следующими способами (HashMap <String, Integer>)
cammando
3
Это вызывает предупреждение о непроверенном приведении. Можно ли это игнорировать?
Мицест
12

Согласно документу , Hashmapорудия Serializable, так что можно putSerializableдогадаться. Вы пробовали?

AMerle
источник
6

Обратите внимание: если вы используете AppCompatActivity, вам нужно будет вызвать метод protected void onSaveInstanceState(Bundle outState) {}( НЕ public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {} ).

Пример кода ...

Сохраните карту:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("leftMaxima", leftMaxima);
    outState.putSerializable("rightMaxima", rightMaxima);
}

И получите его в onCreate:

if (savedInstanceState != null) {
    leftMaxima = (HashMap<Long, Float>) savedInstanceState.getSerializable("leftMaxima");
    rightMaxima = (HashMap<Long, Float>) savedInstanceState.getSerializable("rightMaxima");
}

Извините, если это какой-то дублированный ответ - может кому-то он пригодится. :)

Мартин Пфеффер
источник
4

Если вы хотите отправить все ключи в комплекте, вы можете попробовать

for(String key: map.keySet()){
    bundle.putStringExtra(key, map.get(key));
}
Капил Чаны
источник
Мне любопытно, есть ли причина не делать этого? Я не очень много использовал сериализацию и никогда не связывался с пакетами (новинка для Android), поэтому мне любопытно, если это O (n), а добавление к пакету эффективно O (1) или нет. Если они не отличаются по стоимости, вы не понимаете, зачем вам сериализовать их на другую карту.
Капитан Принни,
@CaptainPrinny, если только карта не является единственной вещью, которую вы сопоставляете с пакетом, вы можете сбивать значения, и вы не узнаете, был ли ключ частью исходной карты или просто значением, хранящимся в пакете.
Джейсон
1
  public static Bundle mapToBundle(Map<String, Object> data) throws Exception {
    Bundle bundle = new Bundle();
    for (Map.Entry<String, Object> entry : data.entrySet()) {
        if (entry.getValue() instanceof String)
            bundle.putString(entry.getKey(), (String) entry.getValue());
        else if (entry.getValue() instanceof Double) {
            bundle.putDouble(entry.getKey(), ((Double) entry.getValue()));
        } else if (entry.getValue() instanceof Integer) {
            bundle.putInt(entry.getKey(), (Integer) entry.getValue());
        } else if (entry.getValue() instanceof Float) {
            bundle.putFloat(entry.getKey(), ((Float) entry.getValue()));
        }
    }
    return bundle;
}
Jasss
источник
1

Я использую свою реализацию Parcelable на kotlin для достижения этой цели, и пока это работает для меня. Это полезно, если вы хотите избежать тяжелой сериализации.

Также для того, чтобы он работал, рекомендую использовать его с этими

Декларация

class ParcelableMap<K,V>(val map: MutableMap<K,V>) : Parcelable {
    constructor(parcel: Parcel) : this(parcel.readMap(LinkedHashMap<K,V>()))

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeMap(map)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<ParcelableMap<Any?,Any?>> {
        @JvmStatic
        override fun createFromParcel(parcel: Parcel): ParcelableMap<Any?,Any?> {
            return ParcelableMap(parcel)
        }
        @JvmStatic 
        override fun newArray(size: Int): Array<ParcelableMap<Any?,Any?>?> {
            return arrayOfNulls(size)
        }
    }

}

Использовать

записывать

val map = LinkedHashMap<Int, String>()
val wrap = ParcelableMap<Int,String>(map)
Bundle().putParcelable("your_key", wrap)

читать

val bundle = fragment.arguments ?: Bundle()
val wrap = bundle.getParcelable<ParcelableMap<Int,String>>("your_key")
val map = wrap.map

Не забывайте, что если ваша карта K,Vпо умолчанию не разбита, они должны реализоватьParcelable

Джоки Доу
источник
1
Вы пытались сократить с помощью @Parcelize?
CoolMind
0

В Котлине:

hashMap = savedInstanceState?.getSerializable(ARG_HASH_MAP) as? HashMap<Int, ValueClass>

putSerializable(ARG_HASH_MAP, hashMap)
CoolMind
источник