Android: Realm + Retrofit 2 + Gson

Store data into Realm through Retrofit 2

I got my answer from Realm official website and other blogs.

My above code is working perfect. Just need to add Realm functionality properly.

In Activity : Dashboard

call.enqueue(new Callback<RealmList<ExampleTest>>() {
@Override
public void onResponse(Call<RealmList<ExampleTest>> call, Response<RealmList<ExampleTest>> response) {

resource = response.body();

Realm.init(DashboardActivity.this);
config = new RealmConfiguration.Builder()
.name("books.realm")
.schemaVersion(1)
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);

// add response to realm database
Realm realm = Realm.getInstance(config);
realm.beginTransaction();
realm.copyToRealmOrUpdate(resource);
realm.commitTransaction();
realm.close();

// programmatically check : data is inserted in to realm or not

int notesCount = realm.where(ExampleTest.class).findAll().size();
int notesCount2 = realm.where(ListConditionalQuestion.class).findAll().size();
int notesCount3 = realm.where(LstHotSpot.class).findAll().size();

Log.d("my first",String.valueOf(notesCount));
Log.d("my second",String.valueOf(notesCount2));
Log.d("my 33333",String.valueOf(notesCount3));

}

@Override
public void onFailure(Call<RealmList<ExampleTest>> call, Throwable t) {

Log.d("fail","response fail");

}
});

Retrofit 2 conflicts with Realm

return Realm.getDefaultInstance().where(SessionVO.class).findAll().toArray(new SessionVO[Realm.getDefaultInstance().where(SessionsRealm.class).findAll().size()]);

This method opens two Realm instances that will never be closed, but on top of that, most of it is completely unnecessary. You can use a RealmResults as a List, so you don't even need an Array.

public RealmResults<SessionVO> getAll(Realm realm){
return realm.where(SessionVO.class).findAll();
}

Although to send it through Retrofit with GSON, you might need to call copyFromRealm before passing it as @Body

Realm and Retrofit2: sending auto-managed objects

Before we dive in

In one of my posts here on Stackoverflow, I have explained what's happening when using Gson and Realm together (Retrofit is just using Gson as a data converter, so it's Gson that's failing not Retrofit). The link is posted down below.

Let's dive in

... only sends the ints in the RealmObject

Nope! Not just ints...

If you look closely, you'll notice that even your ints are set to 0 (which is the null value for an int). The same thing would happen with a boolean, you would get false in the serialized output.

In fact, all your RealmObject attributes are set to null when this same realmObject is managed. When you try to read/write an attribute (from a managed realmObject), Realm will read/write its value from/to the persistence layer (using proxies) so you're sure you're getting/setting the right value of this realmObject (not just getting an old value from the memory).

That being said, I can now explain why Gson is only serializing ints.

  • When your attribute is an object, its value will be equal to null (a reference pointing to nowhere) and Gson won't bother serializing it (you won't see it in the output).

  • When your attribute is a scaler type (char, int, boolean, float ...) its value will be equal to whatever corresponds to a null (every bit in the scalar is 0) and Gson will serialize it cause it's considered to be a valid value. This explains "why only your ints are serialized".

If I however, disconnect the RealmObject from Realm ... then it does
send all fields.

When your realmObject is unmanaged it'll act a normal java object (no proxies are used to maintain the coherence between the object in memory and the persisted one) and of course Gson will have no trouble serializing it.

Is there a proper solution?

There are workarounds. In the post I mentioned earlier, I tried to gather some recommended ones (IMO) to deal this incompatibility. Here's the link: "Android: Realm + Retrofit 2 + GSON".

Android Retrofit + Realm + Gson: Serializer not called

So if register my User type adapter as:

registerTypeAdapter(User.class, new UserSerializer())

instead of:

.registerTypeAdapter(Class.forName("io.realm.UserProxy"), new UserSerializer())

the User serializer is called. I still have no idea why, but it works.

Save relationship from retrofit into realm.

The problem seems to be that in the JSON string "images" is not an array of image objects, but it's a "data" object which itself is in turn an array of image objects.

Do you have control over the JSON format or is it just something you receive and have no control over?

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

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();


Related Topics



Leave a reply



Submit