Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
357 views
in Technique[技术] by (71.8m points)

serialization - ClassCastException when retrieving data from bundle on Android

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...