I have some state that I want to save accross the lifecycle of a fragment. It works fine when the screen rotates for example, but when the process has been killed and restored from disk (I think that's how it works), I get a ClassCastException. Here's some code:
Initialization:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
playlistsMap = new LinkedHashMap<Section, List<Playlist>>();
} else {
playlistsMap = (LinkedHashMap<Section, List<Playlist>>) savedInstanceState.getSerializable(PLAYLISTS_MAP_KEY);
}
setHasOptionsMenu(true);
}
Saving the data :
@Override
public void onSaveInstanceState(Bundle outState) {
if (isEverySectionsLoaded()) {
outState.putSerializable(PLAYLISTS_MAP_KEY, playlistsMap);
} else {
outState.putSerializable(PLAYLISTS_MAP_KEY, new LinkedHashMap<Section, List<Playlist>>());
}
// ...
}
The exception I get from the cast in onCreate
:
04-10 01:06:43.430 E/AndroidRuntime(28549): FATAL EXCEPTION: main
04-10 01:06:43.430 E/AndroidRuntime(28549): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mydomain.android/com.mydomain.android.ui.MainActivity}:
java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
I know it's better to use parcelables on Android, but I still don't understand how that could ever happen.
Any ideas?
Interesting read concerning a similar question can be found here
Any object that implements both java.util.List and java.io.Serializable will become ArrayList after intent.putExtra(EXTRA_TAG, suchObject)/startActivity(intent)/intent.getSerializableExtra(EXTRA_TAG).
I dare to say that the same counts for anything that implements serializable and map. That HashMap is the default you will get back.
A solution around this what seems like a bug would be something similar to:
private LinkedHashMap<Section, List<Playlist>> playlistsMap;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
playlistsMap = new LinkedHashMap<Section, List<Playlist>>();
} else {
//assuming the bug returns a hashmap
Map<Section, List<Playlist>> items = (Map<Section, List<Playlist>>) savedInstanceState.getSerializable(PLAYLISTS_MAP_KEY);
//this way you can ensure you are working with a linkedHashMap.
//for the rest off the application
playlistsMap.putAll(items);
}
setHasOptionsMenu(true);
}
The above code isn't tested but should work. This code will still work when the bug gets fixed due to the usage of interfaces. So you can rest assured when your client gets an android update that your code should still do the same instead of crashing and complaining that you cant cast a HashMap to a LinkedHashMap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With