2013-06-21 13 views
8

Özel bir Java nesnesini serileştirmek istiyorum, böylece SharedPreferences'u saklamak ve başka bir Etkinlikte geri almak için kullanabilirim. Sürekli depolama alanına ihtiyacım yok, SharedPreferences, uygulama kapalıyken bunları siliyorum. Şu anda GSON kullanıyorum, ancak Android'in SparseArray türüyle iyi çalışmıyor gibi görünüyor.Bir SparseArray Dizisi <T> GSON

My nesneleri:

public class PartProfile { 

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

// ... 
} 

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

Seri:

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); 
} 

Seri kaldırma:

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); 
    // ... 
} 

İstisna: GSON benim nesneye bir LinkedTreeMap döküm istiyor neden

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

benim tüm programda birini kullanmak asla anlamıyorum. SparseArray<Part>'a geçmeden önce bir HashMap<Integer,Part> kullanıyordum ve bununla ilgili hiçbir sorun yaşamadım. SparseArrays Gson tarafından desteklenmiyor mu, yoksa benim tarafımda bir hata var mı?

Düzenleme: Görünüşe göre, SparseArray öğesi düzgün bir şekilde seri hale getirilir, ancak içindeki nesneler değil. LinkedTreeMaps yerine, bunlar Part türünde olmalıdır. enter image description here

+0

'SharedPreferences' oturumları boyunca devam eder (uygulama öldürülse bile). [Paylaşılan Tercihleri ​​Kullanarak] 'ı okuyun (http://developer.android.com/guide/topics/data/data-storage.html # pref) – Rajesh

+0

Evet, ancak el ile clear() ile siliyorum. Sadece bunların devam etmesinin gerekli olmadığını belirtmek istedim. – Lennart

+0

'SharedPreferences', etkinliklerin genelinde verileri paylaşmaya yönelik değildir. Daha fazla bilgi için lütfen http://stackoverflow.com/q/3549596/1321873 adresine bakın. – Rajesh

cevap

5

O SparseArray doğru serisi kaldırılan, ancak nesneleri içine alır gibi görünüyor. LinkedTreeMaps yerine, bunlar Part tipinde olmalıdır.

Gözleminiz beri SparseArray (değil Part) Nesne içeren, doğrudur, GSON nesne türü olarak Part yapmak için herhangi bir ipucu olmayacak. Bu nedenle, listenizi meşhur iç tip LinkedTreeMap olarak eşler.

Bunu çözmek için, SparseArray'u kullanamayacağınızı düşünüyorum ... Ya da retreivedParts.get(key).toString()'u deneyebilir, sonra nesneyi yeniden ayrıştırmak için gson'u kullanabilirsiniz.

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; 
    } 

} 

ve bunu kaydetmeniz gerekir kullanmak için: Ama bunun

+0

Cevabınızı kabul edeceğim çünkü buna uygun bir çözüm yok. SparseArrays'ımı HashMaps'le değiştirdim, ancak bir şekilde benim özel nesnelerim bu seçenek etkinleştirilmeden düzgün bir şekilde serileştirilmediğinden, bunları gsm xson yeni GsonBuilder() .istComplexMapKeySerialization(). – Lennart

12

Gerçekten SparseArray her türlü seri hale getirmek için bir yol olduğunu yapmak verimli olduğunu sanmıyorum aşağıda bir örnek koddur Bu gibi Gson nesne, içinde:

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

Eğer this gist bu örnek bulabilirsiniz.

P.S .: En iyi şekilde optimize edilmediğini biliyorum, ancak ihtiyacınız olanı nasıl elde edeceğinize dair bir fikir vermenin sadece bir örneği.

+0

Bu kod çalışır. Ancak, hala SparseArray Parcable/Serializable olmadığı için çözüm olarak kullanmıyorum. Bu nedenle, onu farklı faaliyetlere ve süreçlere aktarmak benim için oldukça zor. Sona, HashMap'e geri dönüyorum. –

+0

Gelecekte referansı bırakacağım https://gist.github.com/dmarcato/6455221 – Javier