Search code examples
androiddatabaseweb-servicesgsonrealm

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:[email protected]},{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


Solution

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

        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                List<Friend> realmFriends = realm.copyToRealmOrUpdate(friends);
                RealmList<Message> realmListFriends = new RealmList<>(realmFriends.toArray(new Friend[friends.size()]));
                user.setFriends(realmListFriends);
            }
        });
    

    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