2013-06-21 169 views
8

我想序列化定製的Java對象,所以我可以用SharedPreferences來存儲它在別的活動retreive它。我不需要持久性存儲,我的應用程序關閉時我擦拭它們。我目前正在使用GSON,但它似乎不適用於Android的SparseArray類型。序列化SparseArray <T>與GSON

我的對象:

public class PartProfile { 

private int gameId; 
// Some more primitives 
private SparseArray<Part> installedParts = new SparseArray<Part>(); 

// ... 
} 

public class Part { 
    private String partName; 
    // More primitives 
} 

連載:

Type genericType = new TypeToken<PartProfile>() {}.getType(); 
String serializedProfile = Helpers.serializeWithJSON(installedParts, genericType); 
preferences.edit().putString("Parts", serializedProfile).commit(); 

serializeWithJSON():

public static String serializeWithJSON(Object o, Type genericType) { 
    Gson gson = new Gson(); 
    return gson.toJson(o, genericType); 
} 

反序列化:

Type genericType = new TypeToken<PartProfile>() {}.getType(); 
PartProfile parts = gson.fromJson(preferences.getString("Parts", "PARTS_ERROR"), genericType); 

SparseArray<Part> retreivedParts = parts.getInstalledParts(); 
int key; 
for (int i = 0; i < retreivedParts.size(); i++) { 
    key = retreivedParts.keyAt(i); 
    // Exception here: 
    Part part = retreivedParts.get(key); 
    // ... 
} 

例外:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.mypackage.objects.Part 

我不明白爲什麼GSON希望蒙上了LinkedTreeMap我的目標,我從來沒有使用一個在我的整個程序。在我切換到SparseArray<Part>之前,我曾經有一個HashMap<Integer,Part>,從來沒有問題。 Gson不支持SparseArrays,還是在我身邊有錯誤?

編輯:看來,SparseArray被內正確反序列化,而不是對象。這些應該是Part而不是LinkedTreeMapsenter image description here

+0

'SharedPreferences'堅持跨會話(即使該應用程序被殺死)。閱讀[使用共享偏好](http://developer.android.com/guide/topics/data/data-storage。html#pref) – Rajesh

+0

是的,但我用clear()手動擦除它們。我只想指出,堅持這些並不是必要的。 – Lennart

+0

'SharedPreferences'不適用於跨活動共享數據。有關更多信息,請參閱http://stackoverflow.com/q/3549596/1321873。 – Rajesh

回答

5

看來,SparseArray被正確地反序列化,而不是裏面的 對象。這些應該是 部分,而不是LinkedTreeMaps。

你的觀察是正確的,因爲SparseArray包含對象(不Part),GSON不會有任何線索,使部分作爲對象類型。因此它會將您的列表映射爲其臭名昭着的內部類型LinkedTreeMap

爲了解決這個問題,我想你將無法使用SparseArray ...或者你可以嘗試retreivedParts.get(key).toString(),然後使用gson來再次解析對象。但我不認爲這是有效的做到這一點

+0

我打算接受你的答案,因爲似乎沒有一個合適的解決方案。我用HashMaps替換了SparseArrays,但是我不得不使用'Gson gson = new GsonBuilder()。enableComplexMapKeySerialization().create()'來序列化它們,因爲我的自定義對象在沒有啓用該選項的情況下未正確反序列化。 – Lennart

12

真的有序列化任何種類的SparseArray的方式,這裏有一個例子代碼:

public class SparseArrayTypeAdapter<T> extends TypeAdapter<SparseArray<T>> { 

    private final Gson gson = new Gson(); 
    private final Class<T> classOfT; 
    private final Type typeOfSparseArrayOfT = new TypeToken<SparseArray<T>>() {}.getType(); 
    private final Type typeOfSparseArrayOfObject = new TypeToken<SparseArray<Object>>() {}.getType(); 

    public SparseArrayTypeAdapter(Class<T> classOfT) { 
     this.classOfT = classOfT; 
    } 

    @Override 
    public void write(JsonWriter jsonWriter, SparseArray<T> tSparseArray) throws IOException { 
     if (tSparseArray == null) { 
      jsonWriter.nullValue(); 
      return; 
     } 
     gson.toJson(gson.toJsonTree(tSparseArray, typeOfSparseArrayOfT), jsonWriter); 
    } 

    @Override 
    public SparseArray<T> read(JsonReader jsonReader) throws IOException { 
     if (jsonReader.peek() == JsonToken.NULL) { 
      jsonReader.nextNull(); 
      return null; 
     } 
     SparseArray<Object> temp = gson.fromJson(jsonReader, typeOfSparseArrayOfObject); 
     SparseArray<T> result = new SparseArray<T>(temp.size()); 
     int key; 
     JsonElement tElement; 
     for (int i = 0; i < temp.size(); i++) { 
      key = temp.keyAt(i); 
      tElement = gson.toJsonTree(temp.get(key)); 
      result.put(key, gson.fromJson(tElement, classOfT)); 
     } 
     return result; 
    } 

} 

,並使用它,你需要進行登錄在Gson對象,像這樣:

Type sparseArrayType = new TypeToken<SparseArray<MyCustomClass>>() {}.getType(); 
Gson gson = new GsonBuilder() 
    .registerTypeAdapter(sparseArrayType, new SparseArrayTypeAdapter<MyCustomClass>(MyCustomClass.class)) 
    .create(); 

你可以找到在this gist這個例子。

P.S:我知道這是不是在所有優化,但它僅是一個例子就如何實現你所需要的一個想法。

+0

此代碼有效。但是,我仍然不使用它作爲SparseArray不是Parcable/Serializable的解決方案。因此,我很難將它傳遞給不同的活動和流程。最終,我回退到HashMap。 –

+0

我將留下未來的參考https://gist.github.com/dmarcato/6455221 – Javier