Skip to content Skip to sidebar Skip to footer

Android - Passing Hashmap Through Intent

I'm trying to pass a Hashmap of custom objects through an intent. I am trying to use parcelable as that's what i read is the correct way to do things in android (i.e. parcelable o

Solution 1:

You can of course serialize your map, as long as your Objects are serializable. What you also could do is creating a separate singleton class (DataStore or so?) that saved your data. This way you don't need to pass the data from Activity to Activity. Or, even simpler, save the data in a public static variable.

Solution 2:

java.util.HashMap is not Parcelable, so your options are:

  • use put/getSerializable, which will work fine within your app
  • encode the HashMap as json or another remotable format if sending outside your app
  • take out the map entries one by one and put them in the Bundle directly (assuming they have string keys)

Solution 3:

You have to add a "wrapper". It is ugly but working...

/**
 * Provides a way to wrap a serializable {@link Map} in order to preserve its class
 * during serialization inside an {@link Intent}, otherwise it would be "flattened"
 * in a {@link android.os.Parcel} and unparceled as a {@link java.util.HashMap}.
 */publicclassMapWrapper<T extendsMap & Serializable> implementsSerializable {

    private final T map;

    publicMapWrapper(@NonNull T map) {
        this.map = map;
    }

    public T getMap() {
        return map;
    }

    /**
     * Add extra map data to the intent. The name must include a package prefix, for example
     * the app com.android.contacts would use names like "com.android.contacts.ShowAll".
     * <p>
     * The provided map will be wrapped to preserve its class during serialization.
     * Use {@link #getMapExtra(Intent, String)} to deserialize it.
     *
     * @param intent The intent to add data to.
     * @param name   The name of the extra data, with package prefix.
     * @param map    The map data value.
     *
     * @return The same {@link Intent} object, for chaining multiple calls into a single statement.
     *
     * @see Intent#putExtra(String, Serializable)
     */@NonNullpublicstatic <T extendsMap & Serializable> IntentputMapExtra(@NonNull Intent intent, @NonNullString name, @NonNull T map) {
        return intent.putExtra(name, newMapWrapper<>(map));
    }

    /**
     * Retrieve extra map data from the intent.
     *
     * @param intent The intent to retrieve data from.
     * @param name   The name of the desired extra item.
     *
     * @return The value of an extra map item that was previously added with
     * {@link #putMapExtra(Intent, String, Map)} or {@code null} if no data was found.
     *
     * @throwsClassCastException
     * If the {@link Serializable} object with the specified name is not of type
     * {@link MapWrapper} or if the wrapped {@code Map} is not of type {@link T}.
     * 
     * @see Intent#getSerializableExtra(String)
     */@Nullablepublicstatic <T extendsMap & Serializable> T getMapExtra(
            @NonNullIntent intent, @NonNullString name)
            throws ClassCastException {
        final Serializable s = intent.getSerializableExtra(name);
        //noinspection uncheckedreturn s == null ? null : ((MapWrapper<T>)s).getMap();
    }

}

More informations on https://medium.com/the-wtf-files/the-mysterious-case-of-the-bundle-and-the-map-7b15279a794e

Post a Comment for "Android - Passing Hashmap Through Intent"