问题
This is a follow-on question from here: Save Bundle to SharedPreferences
I am trying to use the ComplexPreferences class from the aforementioned thread to save a Bundle object in my Android app, but to no avail! Here is the code I'm using to save and load the data to ComplexPreferences (much the same as in the example on the download page for the ComplexPreferences class):
Class1:
save = ComplexPreferences.getComplexPreferences(this, SAVE, MODE_PRIVATE);
...
Bundle gameState = new Bundle();
saveGameData(gameState); // This puts the game data into the Bundle
save.putObject(SAVE, gameState);
save.commit();
Class2:
save = ComplexPreferences.getComplexPreferences(this, Class1.SAVE, MODE_PRIVATE);
...
Bundle gameState = save.getObject(Class1.SAVE, Bundle.class);
The problem appears to be when saving the object to ComplexPreferences. Here is the stack trace I get when running the above code:
FATAL EXCEPTION: main java.lang.RuntimeException: Unable to pause activity {djb.ampersands/djb.ampersands.Ampersands}: java.lang.IllegalStateException: circular reference error Offending field: game Offending object: preserveType: false, type: class djb.ampersands.Ampersands, obj: djb.ampersands.Ampersands@41272778 at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2838) at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2794) at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2772) at android.app.ActivityThread.access$800(ActivityThread.java:130) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1206) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.IllegalStateException: circular reference error Offending field: game Offending object: preserveType: false, type: class djb.ampersands.Ampersands, obj: djb.ampersands.Ampersands@41272778 at com.google.gson.JsonSerializationVisitor.visitObjectField(JsonSerializationVisitor.java:117) at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:69) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120) at com.google.gson.JsonSerializationVisitor.getJsonElementForChild(JsonSerializationVisitor.java:147) at com.google.gson.JsonSerializationVisitor.addAsChildOfObject(JsonSerializationVisitor.java:127) at com.google.gson.JsonSerializationVisitor.visitObjectField(JsonSerializationVisitor.java:114) at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:69) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120) at com.google.gson.JsonSerializationVisitor.getJsonElementForChild(JsonSerializationVisitor.java:147) at com.google.gson.JsonSerializationVisitor.addAsChildOfObject(JsonSerializationVisitor.java:127) at com.google.gson.JsonSerializationVisitor.visitObjectField(JsonSerializationVisitor.java:114) at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:69) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120) at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:62) at com.google.gson.BaseMapTypeAdapter.serialize(BaseMapTypeAdapter.java:34) at com.google.gson.MapTypeAdapter.serialize(MapTypeAdapter.java:53) at com.google.gson.MapTypeAdapter.serialize(MapTypeAdapter.java:33) at com.google.gson.JsonSerializationVisitor.findAndInvokeCustomSerializer(JsonSerializationVisitor.java:184) at com.google.gson.JsonSerializationVisitor.visitFieldUsingCustomHandler(JsonSerializationVisitor.java:204) at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:63) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120) at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:62) at com.google.gson.JsonSerializationContextDefault.serialize(JsonSerializationContextDefault.java:53) at com.google.gson.Gson.toJsonTree(Gson.java:220) at com.google.gson.Gson.toJson(Gson.java:260) at com.google.gson.Gson.toJson(Gson.java:240) at djb.ampersands.gui.ComplexPreferences.putObject(ComplexPreferences.java:47) at djb.ampersands.Ampersands.onPause(Ampersands.java:93) at android.app.Activity.performPause(Activity.java:5106) at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1225) at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2825) ... 12 more Caused by: com.google.gson.CircularReferen
Since the object was saved incorrectly, it makes sense that I also get an error when trying to load the object again:
java.lang.IllegalArgumentException: Object storaged with key save is instanceof other class at djb.ampersands.gui.ComplexPreferences.getObject(ComplexPreferences.java:63)
Summary: When I first wrote this question, I said I couldn't get any objects to save/load correctly. However, I have now got this method to work for some objects, so really my question now is, can it ever work for Bundle objects, and the answer, it would appear, is no... so I guess it's back to the drawing board!
回答1:
You should not save your bundle entirely but only your gameState
object. Bundles might be more complex to serialize than a simple POJO.
As the lib uses Json to serialize things, it expects a simple POJO and Bundles are definitely not simple POJOs : some fields of the Bundle class will never be serialized correctly in Json, especially the class loader.
来源:https://stackoverflow.com/questions/13665389/saving-bundle-with-android-complexpreferences-json