2

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
dimsuz
  • 8,969
  • 8
  • 54
  • 88
  • I would guess it's because ImmutableMap has it's own serialization. HashMap appears to be imported in ImmutableMap but I don't see where it's used. Unsure of how it would resolve to HashMap. I'll keep digging. – Pieces Jun 04 '14 at 13:43

1 Answers1

1

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")
  );
}
Etienne Neveu
  • 12,604
  • 9
  • 36
  • 59