Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
356 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 Reply

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...