rosu alin rosu alin - 4 months ago 9
Android Question

Issue setting a RealmList<Object> to my database item, using Realm for android

First I call a function that will bring back my user from the database, and after I get my updated profile from the WS, and I try to change the list of friends from the database.

Method to get my user:

public UserRecord getMyUser(){
String userId = PSLocationCenter.getInstance().pref.getUserId(context);
RealmResults<UserRecord> completed = realm.where(UserRecord.class).equalTo("id" , userId).findAll();
if(completed.size() > 0){
return completed.get(0);
}else{
return null;
}
}


After that , this is the WSCall from which I get the data, and try to change the friends list:

user = UserRecordDBFactory.getInstance(PSProfileActivity.this).getMyUser();
WSCalls.getData("/api/users/" + user.getId() + "/friends", PSProfileActivity.this, loader, new JsonCallback() {
@Override
public void onResponse(JSONObject jsonObject) {
try {
FriendsResponse friendsResponse = JsonUtil.jsonToObject(jsonObject.toString(), FriendsResponse.class);
Log.i("","friends response: " + friendsResponse.toString());
Log.i("","friends response: " + friendsResponse.getFriends());
friends = friendsResponse.getFriends();
Log.i("","friends after being given the response: " + friends.size());
Log.i("","friends USER after being given the response: " + user);
Log.i("","friends USER after being given the response: " + user.getId());
Realm realm = Realm.getInstance(PSProfileActivity.this);
realm.beginTransaction();
user.setFriends(friends);
Log.i("", "friends set to user: " + friends);
realm.commitTransaction();
UserRecordDBFactory.getInstance(PSProfileActivity.this).updateMyUser(user);
Log.i("", "friends set to user in REALM: " + friends);
setHeaderAndData(profile);
} catch (Exception e) {
Utils.appendLog("onresume friends activ error: " + e.getMessage());
Log.e("", "getProfileData - JsonException: " + e.getMessage());
}
}
});


This is the log I get back:

03-10 18:02:13.826 23882-23882/nl.hgrams.passenger I/﹕ friends response: nl.hgrams.passenger.model.FriendsResponse@1635594a
03-10 18:02:13.827 23882-23882/nl.hgrams.passenger I/﹕ friends response: RealmList@[254263483,474495448,561029425,720879638,789032343,921901956,66920301,229099426,948931635,877161456,1062815081,73317358,28096655,610293532,322424613,192850170,667307691]
03-10 18:02:13.827 23882-23882/nl.hgrams.passenger I/﹕ friends after being given the response: 17
03-10 18:02:13.829 23882-23882/nl.hgrams.passenger I/﹕ friends USER after being given the response: UserRecord = [{username:},{first_name:Alin},{last_name:Red},{email:r@y.com},{token:8596bcb0243cc16b6f16e5e90210754c65f8e58ca426daecd3d7220d5092e24d},{id:6},{bio:Red},{image:/media/user_image/8b824838993f3c5aae2bfb650851e7e1.jpe},{nrTrips:0},{distance:0},{last_destination:},{friends:RealmList<Friend>[0]},{activityLog:null},{recents:RealmList<SearchData>[0]},{updateRecents:false}]
03-10 18:02:13.829 23882-23882/nl.hgrams.passenger I/﹕ friends USER after being given the response: 6
03-10 18:02:13.836 23882-23882/nl.hgrams.passenger E/﹕ getProfileData - JsonException: Attempt to invoke virtual method 'long io.realm.internal.Row.getIndex()' on a null object reference


This is my setter from the RealmObject class:

public void setFriends(RealmList<Friend> fr) {
Log.i("","before in set friends");
friends = fr;
Log.i("","after in set friends");
}


And it doesn't log neither of the logs from the getter. As you can see I also made logs to check if user or friends are null, but it's not the case.
Any ideea what I'm doing wrong here?
Seeing that it tried long io.realm.internal.Row.getIndex(), I'm guessing it finds the user somehow null, but why?

This is what the jsonToObject function does:

public static <T> T jsonToObject(String json, Class<T> toClass) throws Exception {
if (instance == null) {
instance = new JsonUtil();
}
return instance.gson.fromJson(json, toClass);
}


Where the instance gson is:

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


And I only have RealmObjects inside my UserRecord, I do not use normal objects

Answer

I believe you can avoid iterating over all of your friends and add them individually if you do something like this:

    realm.beginTransaction();
    List<Friend> realmFriends = realm.copyToRealmOrUpdate(friends);
    RealmList<Message> realmListFriends = new RealmList<>(realmFriends.toArray(new Friend[friends.size()]));
    user.setFriends(realmListFriends);
    realm.commitTransaction();

EDIT: Just to be clear, you are still iterating over your friends internally inside the method Collection.toArray(). The complexity is still O(n), but the code is more readable