2013-06-21 2 views
8

SharedPreferences을 사용하여 다른 Java 활동에 저장하고 검색 할 수 있도록 사용자 정의 Java 객체를 직렬화하려고합니다. 영구 저장 장치가 필요하지 않습니다. SharedPreferences은 응용 프로그램이 닫히면 지워집니다. 현재 GSON을 사용하고 있지만 Android의 SparseArray 유형과 잘 작동하지 않는 것 같습니다.SparseArray를 직렬화하기 <T> with 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); 
    // ... 
} 

예외 : GSON 내 개체에 LinkedTreeMap 캐스팅하고 싶은 이유를

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

나는 내 전체 프로그램에서 하나를 사용하지 않습니다, 이해가 안 돼요. 이전에 SparseArray<Part>으로 전환하기 전에 나는 HashMap<Integer,Part>을 사용 했었지만 문제는 없었습니다. Gear가 SparseArrays를 지원하지 않습니까? 아니면 저의 편에 오류가 있습니까?

편집 : SparseArray가 올바르게 역 직렬화되지만 내부의 개체는 역 직렬화되지 않는 것으로 보입니다. LinkedTreeMaps 대신 Part이어야합니다. enter 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

IT는 SparseArray가 제대로 직렬화 아닌 객체 내부 도착 것으로 보인다. LinkedTreeMaps 대신 Part 유형이어야합니다.

귀하의 관찰 이후 SparseArray는 (안 Part)를 개체 포함, 정확, GSON는 개체 유형으로 제품을 만들 수있는 단서가되지 않습니다. 따라서 악명 높은 내부 유형 인 LinkedTreeMap으로 목록을 매핑합니다.

문제를 해결하려면 SparseArray을 사용할 수 없다고 생각하거나 retreivedParts.get(key).toString()을 시도한 다음 gson을 사용하여 개체를 다시 구문 분석하십시오.

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

} 

하고 등록해야이 기능을 사용하려면하지만 그것은

+0

적절한 해결책이 보이지 않아 답변을 수락 할 것입니다. 내 SparseArrays를 HashMaps로 바꿨지 만, 내 사용자 지정 개체가 해당 옵션을 사용하지 않고 제대로 deserialize되지 않았기 때문에'Gson gson = new GsonBuilder(). enableComplexMapKeySerialization(). create()'를 사용하여 serialize해야했습니다. – Lennart

12

정말 SparseArray의 어떤 종류를 직렬화 할 수있는 방법이 있다는 것을 어떻게 효율적으로 생각하지 않습니다, 여기에 예제 코드입니다 이처럼 Gson 개체에서 :

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

당신은 this gist이 예를 찾을 수 있습니다.

P .: 나는 이것이 전혀 최적화되지 않았 음을 알고 있지만, 필요한 것을 성취하는 방법에 대한 아이디어를 제공하는 예일뿐입니다.

+0

이 코드는 작동합니다. 그러나 SparseArray는 Parcable/Serializable이 아니므로 솔루션으로 사용하지 않습니다. 따라서 다른 활동과 프로세스로 전달하는 것은 꽤 어렵습니다. 결국, 나는 HashMap으로 돌아 간다. –

+0

나는 미래의 참고 문헌을 남길 것이다. https://gist.github.com/dmarcato/6455221 – Javier