2017-09-11 10 views
0

J'ai 2 classes comme l'exemple de code suivant:récursive Objets problème de sérialisation avec ORMLite 5 et retrofit 2

Classe A

@DatabaseField(id = true, columnName = "id") 
private UUID id; 
@ForeignCollectionField 
private LazyForeignCollection<B, UUID> bList; 

Classe B

@DatabaseField(id = true) 
private UUID id; 
@DatabaseField(columnName = "idA", foreign = true) 
private A objA; 
@DatabaseField 
private String foo; 

Je suis confronté à des problèmes pour envoyer ces données d'android à une API en utilisant Retrofit2, car lorsque j'envoie A, l'appel du sérialiseur le bList et ORMLite le chargeront automagiquement.

Chaque objet de B dans ma liste b a rempli "objA" et chaque "objA" a une liste de données. Son OK pour l'application, car il est toujours le même objet alloué, mais le sérialiseur GSon essaie de sérialiser tous les niveaux et génère cette exception:

ERR: stack=java.lang.RuntimeException: An error occured while executing doInBackground() 
                   at android.os.AsyncTask$3.done(AsyncTask.java:304) 
                   at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
                   at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
                   at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
                   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
                   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
                   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
                   at java.lang.Thread.run(Thread.java:818) 
                  Caused by: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed. # Open Cursors=760 (# cursors opened by this proc=760) 
                   at android.database.CursorWindow.<init>(CursorWindow.java:108) 
                   at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198) 
                   at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139) 
                   at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) 
                   at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197) 
                   at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237) 
                   at com.j256.ormlite.android.AndroidDatabaseResults.first(AndroidDatabaseResults.java:68) 
                   at com.j256.ormlite.android.AndroidDatabaseConnection.queryForOne(AndroidDatabaseConnection.java:206) 
                   at com.j256.ormlite.stmt.mapped.MappedQueryForFieldEq.execute(MappedQueryForFieldEq.java:38) 
                   at com.j256.ormlite.field.FieldType.createForeignObject(FieldType.java:1047) 
                   at com.j256.ormlite.field.FieldType.assignField(FieldType.java:556) 
                   at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:72) 
                   at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:284) 
                   at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:168) 
                   at com.j256.ormlite.stmt.SelectIterator.next(SelectIterator.java:181) 
                   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96) 
                   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) 
                   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239) 
                   at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:968) 
                   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239) 
                   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
                   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) 
                   at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) 
                   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239) 
                   at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:968) 
                   at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112) 
                   at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239) 
                  at com.google.gson.internal.bind.TypeAdapterRuntime 

et ceci:

09-11 09:59:16.618 28706-28747/br.com.igtech.nr18 D/Error: ERR: TOTAL BYTES WRITTEN: 1636884 
09-11 09:59:16.618 28706-28747/br.com.igtech.nr18 E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! 
09-11 09:59:16.628 28706-28747/br.com.igtech.nr18 E/AndroidRuntime: Error reporting crash 
                    android.os.TransactionTooLargeException 
                     at android.os.BinderProxy.transactNative(Native Method) 
                     at android.os.BinderProxy.transact(Binder.java:496) 
                     at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:4164) 
                     at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:89) 
                     at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693) 
                     at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690) 

Mannualy définissant l'objet de null peut résoudre ce problème, mais je pense que ce n'est pas la meilleure façon de le faire.

Répondre

0

Lire this et this

Résolu changer la ConverterFactory de Gson à Jackson

retrofit = new Retrofit 
       .Builder() 
       .baseUrl(baseUrl) 
       .addConverterFactory(JacksonConverterFactory.create()) 
       .client(okHttpClient) 
       .build(); 

Jackson a les @JsonManagedReference et @JsonBackReference annotations qui permettent de résoudre le problème de la boucle.