Question

I am using Guava collections in an Android project. Just noticed the following behavior:

In Activity1:

Intent i = new Intent(this, Activity2.class);
i.putExtra("extra1", ImmutableMap.of("key1", "value1"));
startActivity(i);

In Activity2:

Activity2::onCreate(...) {
  ImmutableMap<String,String> map = 
         (ImmutableMap<String,String>)getIntent()
              .getSerializableExtra("extra1");
  // above line throws ClassCastException!
}

Once executed, code in the second snippet throws this exception:

java.lang.ClassCastException: java.util.HashMap cannot be cast to com.google.common.collect.ImmutableMap

So at some point ImmutableMap gets turned into a HashMap. I wonder why is that and what can I do to avoid this?

P.S. If I print this to debug output right after constructing/receiving an Intent:

intent.getSerializableExtra("extra1").getClass().getSimpleName());
// ^^^^ prints SingletonImmutableBiMap in Activity1
// ^^^^ prints HashMap in Activity2
Was it helpful?

Solution

The Intent extras are passed around as parcels, which is a high-performance IPC transport (think high-performance serialization). When parcelled, your ImmutableMap is written like all Map implementations, and thus it is later read as a HashMap.

I don't think you can avoid this. If you really want to work with an ImmutableMap, you'd need to use ImmutableMap.copyOf() to copy the HashMap's content into an ImmutableMap.

Activity2::onCreate(...) {
  ImmutableMap<String,String> map = ImmutableMap.copyOf(
         (Map<String,String>)getIntent().getSerializableExtra("extra1")
  );
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top