Retrofit + RealmList + Gson stuck in a loop until out of memory

一笑奈何 提交于 2019-11-27 18:44:10

问题


I'm trying to user Retrofit + Realm + Gson, but when the RealmList is used the app get stuck.

If I remove the RealmList objects everything work's fine, but I need the object list.

Logcat:

(32099): Background sticky concurrent mark sweep GC freed 278516(15MB) AllocSpace objects, 0(0B) LOS objects, 25% free, 23MB/31MB, paused 2.533ms total 1.049s
(32099): Background partial concurrent mark sweep GC freed 137132(8MB) AllocSpace objects, 0(0B) LOS objects, 40% free, 23MB/39MB, paused 4.211ms total 188.951ms
(32099): Background sticky concurrent mark sweep GC freed 271335(15MB) AllocSpace objects, 0(0B) LOS objects, 24% free, 24MB/32MB, paused 3.998ms total 236.868ms
(32099): Background sticky concurrent mark sweep GC freed 143812(8MB) AllocSpace objects, 0(0B) LOS objects, 23% free, 24MB/32MB, paused 6.470ms total 201.800ms
(32099): Background partial concurrent mark sweep GC freed 159223(9MB) AllocSpace objects, 0(0B) LOS objects, 39% free, 23MB/39MB, paused 5.524ms total 215.809ms
(32099): Background sticky concurrent mark sweep GC freed 278158(15MB) AllocSpace objects, 0(0B) LOS objects, 24% free, 24MB/32MB, paused 1.922ms total 201.617ms

Json:

[
{
  "id": "1",
  "title": "Subcategory 1",
  "color": "FF0000",
  "tabs": [
    {
      "id": "1",
      "title": "Tab 1"
    },
    {
      "id": "2",
      "title": "Tab 2"
    }
  ]
},
{
  "id": "2",
  "title": "Subcategory 2",
  "color": "DD0000",
  "tabs": [
    {
      "id": "1",
      "title": "Tab 1"
    },
    {
      "id": "2",
      "title": "Tab 2"
    }
  ]
}
]

Subcategory class:

public class Subcategory extends RealmObject {

@SerializedName("id")
private String id;
@SerializedName("title")
private String title;
@SerializedName("color")
private String color;

@SerializedName("tabs")
private RealmList<Tab> tabs;

... sets & gets ...

}

Tab class:

public class Tab extends RealmObject {

@SerializedName("id")
private String id;
@SerializedName("title")
private String title;

... sets & gets ...
}

RestClient use:

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

services = retrofit.create(Services.class);

services.getSubcategories().enqueue(new Callback<RealmList<Subcategory>>() {
        @Override
        public void onResponse(Response<RealmList<Subcategory>> response) {
            Log.e(TAG, "Size: " + response.body().size());
        }

        @Override
        public void onFailure(Throwable t) {
            t.printStackTrace();
        }
    });

Libs:

compile 'io.realm:realm-android:0.87.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'

回答1:


You need to configure an ExclusionStrategy for GSON as described here: https://realm.io/docs/java/latest/#gson

Gson gson = new GsonBuilder()
        .setExclusionStrategies(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return f.getDeclaringClass().equals(RealmObject.class);
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return false;
            }
        })
        .create();

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

Update: From Realm 0.89 it should no longer be necessary to define the exclusion strategy, the below should be enough:

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();



回答2:


I was facing the same issue and the accepted answer didn't work for me despite of having realm version above 0.87. I am posting this in case anyone else faces this issue and accepted answer doesn't work.

I got it working by converting RealmList<MyModel> to List<MyModel> using ream.copyFromRealm function which creates in-memory copy of realm objects.

Something like this should work:

RealmList<MyModel> myModelRealmObjects = realmDBManager.getModelObjects();
List<MyModel> myModelObjects = realm.copyFromRealm(myModelRealmObjects);

And then pass myModelObjects to retrofit.



来源:https://stackoverflow.com/questions/34735639/retrofit-realmlist-gson-stuck-in-a-loop-until-out-of-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!