3

What happened:

  1. I have multiple objects saved in an arraylist that is saved in a gson string.
  2. I change the class of the object (to include more variables and getter/setter methods)
  3. Now I run into errors when trying to load the older objects (saved in step 1)

Things to consider:

I use gson/json to store the arraylist in an android shared preference. (the shared preference works fine for other values, the error appears to be when converting the string into an arraylist with json/gson)

My code:

    public void loadDataSavedMatches() {
    SharedPreferences prefs = getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE);
    Gson gson = new Gson();
    String json = prefs.getString("task list", null);
    Type type = new TypeToken<ArrayList<TennisMatch>>() {
    }.getType();
    mTennisMatches = gson.fromJson(json, type);

    if (mTennisMatches == null) {
        mTennisMatches = new ArrayList<>();
    }

    Log.i("LOAD DATA", String.valueOf(mTennisMatches));
    Log.i("LOAD DATA2", String.valueOf(prefs));

    //hashMap


    SharedPreferences hashPrefs = getSharedPreferences(HASH_MAP_SHARED_PREFS_FILE, Context.MODE_PRIVATE);
    Gson hashGson = new Gson();
    String hashJson = hashPrefs.getString("hashString", null);
    Type hashType = new TypeToken<HashMap<String, TennisMatch>>() {
    }.getType();
    item_map = hashGson.fromJson(hashJson, hashType);

    if (item_map == null) {
        item_map = new HashMap<String, TennisMatch>();
    }

}

Error message:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.myapp, PID: 28341
java.lang.AssertionError: impossible
    at java.lang.Enum$1.create(Enum.java:45)
    at java.lang.Enum$1.create(Enum.java:35)
    at libcore.util.BasicLruCache.get(BasicLruCache.java:54)
    at java.lang.Enum.getSharedConstants(Enum.java:211)
    at java.lang.Class.getEnumConstants(Class.java:1063)
    at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(TypeAdapters.java:778)
    at com.google.gson.internal.bind.TypeAdapters$30.create(TypeAdapters.java:817)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
    at com.google.gson.Gson.getAdapter(Gson.java:423)
    at com.google.gson.Gson.fromJson(Gson.java:887)
    at com.google.gson.Gson.fromJson(Gson.java:853)
    at com.google.gson.Gson.fromJson(Gson.java:802)
    at com.android.myapp.Activity.loadDataSavedMatches(ItemMatchListActivity.java:282)
    at com.android.myapp.Activity.onCreate(ItemMatchListActivity.java:87)
    at android.app.Activity.performCreate(Activity.java:6102)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2403)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
    at android.app.ActivityThread.access$1200(ActivityThread.java:165)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5593)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
 Caused by: java.lang.NoSuchMethodException: values []
    at java.lang.Class.getMethod(Class.java:664)
    at java.lang.Class.getDeclaredMethod(Class.java:626)
    at java.lang.Enum$1.create(Enum.java:41)
    at java.lang.Enum$1.create(Enum.java:35) 
    at libcore.util.BasicLruCache.get(BasicLruCache.java:54) 
    at java.lang.Enum.getSharedConstants(Enum.java:211) 
    at java.lang.Class.getEnumConstants(Class.java:1063) 
    at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(TypeAdapters.java:778) 
    at com.google.gson.internal.bind.TypeAdapters$30.create(TypeAdapters.java:817) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53) 
    at com.google.gson.Gson.getAdapter(Gson.java:423) 
    at com.google.gson.Gson.fromJson(Gson.java:887) 
    at com.google.gson.Gson.fromJson(Gson.java:853) 
    at com.google.gson.Gson.fromJson(Gson.java:802) 
    at com.android.myapp.Activity.loadDataSavedMatches(ItemMatchListActivity.java:282) 
    at com.android.myapp.Activity.onCreate(ItemMatchListActivity.java:87) 
    at android.app.Activity.performCreate(Activity.java:6102) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2403) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 
    at android.app.ActivityThread.access$1200(ActivityThread.java:165) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5593) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

Thank you for your help!

jonasxd360
  • 1,225
  • 4
  • 19
  • 35
  • I think one way could be to have both object classes available. Then put an attribute with new prefs that if present will indicate which object type to use to parse the data. Use old object type to parse old data and new object type to read new data. – muasif80 Feb 24 '19 at 02:10
  • Another option could be to read the old prefs using old object type and save it with new object type. – muasif80 Feb 24 '19 at 02:11
  • This could be done as part of the upgrade for the android app – muasif80 Feb 24 '19 at 02:12
  • @muasif80 Do you think renaming the old object to oldObjectName would be fine? Or should I keep the name? Can I still have old and new objects in a Arraylist? – jonasxd360 Feb 24 '19 at 13:20

2 Answers2

2

See Android release APK crash with java.lang.AssertionError: impossible in java.lang.Enum, AssertionError in Gson EnumTypeAdapter when using Proguard Obfuscation or https://github.com/zendesk/sunshine-conversations-android/issues/93. In proguard-rules.pro add:

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
CoolMind
  • 26,736
  • 15
  • 188
  • 224
0

Some of the new Data I was including were Firebase DocumentReferences & CollectionReferences, I noticed that these data types don't play nicely with gson/json and therefore I excluded them. I am thinking about using a string to save the Document and Collection Reference instead.

//    private CollectionReference mColRef; //I removed this from my Object 
//    private DocumentReference mDocRef;
jonasxd360
  • 1,225
  • 4
  • 19
  • 35