2014-09-10 124 views
2

我試圖在活動之間傳遞一個序列化的LinkedHashMap,並且在反序列化對象時得到一個令人困惑的結果/錯誤。Android LinkedHashMap反序列化爲HashMap,導致CCE錯誤

序列化對象如下:

Bundle exDetails = new Bundle(); 
    LinkedHashMap<String, Exercise> exMap = new LinkedHashMap<String, 
    Exercise (workout.getExercises()); 

    exDetails.putString(WORKOUTNAME, workout.getWorkoutName()); 
    exDetails.putSerializable(workout.getWorkoutName(), exMap); 

    iComplete.putExtra("wName", exDetails); 
    startActivity(iComplete); 

這似乎很好地工作,這個問題表明了在未來的活動:

Bundle exDetails = getIntent().getBundleExtra("wName"); 
    workoutName = exDetails.getString(WORKOUTNAME); 
    Serializable eData = exDetails.getSerializable(workoutName); 

    ex = new LinkedHashMap<String, Exercise>(); 
    ex = (LinkedHashMap<String, Exercise>) eData; 

此時,反序列化對象(EDATA)包含一個HashMap對象(不是LinkedHashMap),它給我在最後一行上的

java.lang.ClassCastException:java.util.HashMap cannot be 
cast to java.util.LinkedHashMap 

。我已經通過調試器驗證了包(在第二個活動中)包含一個HashMap,而不是LinkedHashMap(因爲我假設它應該)。我還應該提到,我需要維護向Map中添加條目的順序,因此需要使用LinkedHashMap。這些條目最終會打印出來,順序對輸出非常重要。

問題: 我是否做了特別錯誤的事情,還是由於LinkedHashMap的序列化錯誤導致此問題?我注意到一些類似的線程,似乎說這是幾個Map實現的持續問題。他們沒有直接回答我的問題。

如果是後者,是否有一個解決方法不是太先進(我不是遠遠超出初學者水平,但我願意嘗試大多數事情),還是我只需要咬緊牙關就行了除了LinkedHashMap以外的東西?

P.s.我試圖包含所有相關內容,但如果我忽略了任何重要的內容,我可以添加更多代碼。

+0

我的代碼一直工作正常。突然之間,我有了這個例外,無處不在。由於沒有明顯的原因,Parcelable也在崩潰。我猜他們在某處銷燬了一些代碼。 – 2014-12-11 13:18:01

+0

我有相同的問題,並且在測試Android 5.0或更高版本中的代碼後,此錯誤開始出現。我不得不實施一個像[這一個](http://stackoverflow.com/questions/15922572/classcastexception-when-retrieving-data-from-bundle-on-android)的解決方法 – Juancho 2015-05-18 13:38:14

+0

Android將'LInkedHashMap'轉換爲'當它通過'Bundle'被序列化/反序列化時,它就是'Hashmap'。看到我的回答這個問題和更多血淋淋的細節鏈接的問題:http://stackoverflow.com/a/38960732/769265 – 2016-08-15 18:48:36

回答

0

我採用了不同的方法:將任何(類型)Map映射爲2個ArrayLists:一個包含鍵,另一個包含值。這樣,地圖條目的順序(在LinkedHashMap中很重要)就被保留下來了。

每個鍵/值實現Serializable。如果您確實知道只需要字符串或者只是一種特定類型的Map,那麼將以下通用代碼轉換爲所需的方案應該非常容易,這也簡化了複雜性。

地圖 - > 2周的ArrayList:

public static <K extends Serializable, V extends Serializable> Pair<ArrayList<K>, ArrayList<V>> convertMapToArrays(@NonNull Map<K, V> map) { 
     final Set<Map.Entry<K, V>> entries = map.entrySet(); 
     final int size = entries.size(); 
     final ArrayList<K> keys = new ArrayList<>(size); 
     final ArrayList<V> values = new ArrayList<>(size); 
     for (Map.Entry<K, V> entry : entries) { 
      keys.add(entry.getKey()); 
      values.add(entry.getValue()); 
     } 
     return new Pair<>(keys, values); 
} 

2的ArrayList - >特定類型的地圖

public static <K extends Serializable, V extends Serializable> Map<K, V> convertArraysToMap(@NonNull ArrayList<K> keys, @NonNull ArrayList<V> values, @NonNull Class<? extends Map<K, V>> mapClass) { 
     if (keys.size() != values.size()) { 
      throw new RuntimeException("keys and values must have the same number of elements"); 
     } 
     final int size = keys.size(); 
     Map<K, V> map; 
     try { 
      final Constructor<? extends Map<K, V>> constructor = mapClass.getConstructor(Integer.TYPE); 
      map = constructor.newInstance(size); 
     } catch (Exception nse) { 
      throw new RuntimeException("Map constructor that accepts the initial capacity not found."); 
     } 

     for (int i = 0; i < size; i++) { 
      final K key = keys.get(i); 
      final V value = values.get(i); 
      map.put(key, value); 
     } 
     return map; 
    } 

助手Android版的軟件包:

public static <K extends Serializable, V extends Serializable> void saveMapToBundleAsArrays(@NonNull Map<K, V> map, @NonNull String key, @NonNull Bundle bundle) { 
     final Pair<ArrayList<K>, ArrayList<V>> mapToArrays = convertMapToArrays(map); 
     final String keyForKeys = key + "_keys"; 
     final String keyForValues = key + "_values"; 
     bundle.putSerializable(keyForKeys, mapToArrays.first); 
     bundle.putSerializable(keyForValues, mapToArrays.second); 
    } 

public static Map<Serializable, Serializable> loadMapFromBundle(@NonNull Bundle bundle, @NonNull String key, @NonNull Class<? extends Map<Serializable, Serializable>> mapClass) { 
     final String keyForKeys = key + "_keys"; 
     final String keyForValues = key + "_values"; 
     final ArrayList<Serializable> keys = (ArrayList<Serializable>) bundle.getSerializable(keyForKeys); 
     final ArrayList<Serializable> values = (ArrayList<Serializable>) bundle.getSerializable(keyForValues); 
     return convertArraysToMap(keys, values, mapClass); 
    } 

用法:15周

saveMapToBundleAsArrays(mModelEvolution, KEY_MODEL_DATA, bundle); 

Class<LinkedHashMap<Serializable, Serializable>> linkedHashMapClazz = 
       (Class<LinkedHashMap<Serializable, Serializable>>) new LinkedHashMap<String, String>().getClass(); 
mModelEvolution = (LinkedHashMap) ObjectUtils.loadMapFromBundle(bundle, KEY_MODEL_DATA, linkedHashMapClazz);