I am using retrofit 2.2.0 and Realm 3.1.4.
I am posting a realm object "Car" to server. Object has all the values initialised. I can see the value both in The app UI, and through expression evaluation. but when I post the object the parsed object has all the values empty. I have the debugging on in Retrofit with log level BODY. So OKHttp is printing the body of request which is json of this object, which as all the keys & values but all the values are the default values like 0, which are set in object creation.
I tried everything else, nothing worked BUT creating a new object, initializing its values with the values of the object from DB and then posting this new copy object without saving it to DB works fine.
This problem has wasted about a DAY of mine.
I can post the object of same class. saved in DB from another activity. but somehow the object is parsed as empty in this particular case every single time. I do not know how to reproduce this. Only one search result has came back with the same issue as this that is. http://stackoverflow.com/questions/31593724/realm-object-is-empty-when-posting-with-retrofit
this is my first post here. excuse my mistakes if any.
Realm version(s): ?
classpath "io.realm:realm-gradle-plugin:3.1.4"
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
Realm sync feature enabled: no
Android Studio version: 2.3.1
Android 6.0 , Samsung A7 2015
@ahmadzkn you are running into https://realm.io/docs/java/latest/#android-studio-debugging and before you send a managed RealmObject through a reflection-based JSON serializer, you should call realm.copyFromRealm(obj).
@Zhuinden this has worked. Really appreciate your response.
can you help me understand this further as I am confused a little bit about it.
Does one not get a managed object when
realm.where(Car.class).equalTo("primaryID", carId).findFirst();
is used ?
I can't edit anything on this object I have to do it in the transaction otherwise I get an exception. saying I should edit managed object inside of a transaction.
Thank you.
@ahmadzkn the trick is that realm.where(Car.class).equalTo("primaryID", carId).findFirst(); indeed returns a managed object.
Managed object means that it is a "live view of the object in the database", but as Realm is transactional and MVCC, these objects aren't modified unless in a transaction, or if Realm on that thread is notified that a transaction happened on some thread. This is when RealmChangeListeners are called.
Now, what is important here is that the object is a view (a "proxy"), in the sense that it does not contain any data, hence why they are all 0 and null. This is because the data is read from the database only when you actually read from the fields (String data = thing.myDataField;) because it gets converted to the proxy accessor method you see in ___RealmProxy classes.
But GSON reads fields with reflection instead of accessors, so it will read the empty proxy fields instead of the accessors.
Realm gives you copyFromRealm() if you truly need to have an unmanaged object detached from the database that can have its fields modified and filled up with data in that given "version" of the Realm. So that's why you generally only need it if you want to fill out some form where you only "save" when you explicitly click the save button, or if you want to send it through a JSON serializer.
@Zhuinden Thank your for such a detailed explanation.
Can you please also tell what would be the best practice here. For when I want to submit a form I should get an unmanaged object from the database using copyFromRealm. After editing that object I should copyOrUpdate that object to realm?
Would this be called a good practice ? or should one adopt a different one ?
generally I recommend insertOrUpdate if you don't need the proxy that is returned, but yes.
@ahmadzkn Working on unmanaged data and only save it once a user presses "Save" is easier to implement, but will also mean they will loose whatever data they happened to have entered if then the app crashes or is put into the background and closed (e.g. if the phone rings).
In the end, it boils down to what kind of user experience you want to give.
In any case, your original question was answered. So I'll close this issue.
Technically that's when Parceler comes into play, without the ˙implementations={XRealmProxy.class}` setting. That way you can persist unmanaged obj. in bundle
Most helpful comment
@ahmadzkn you are running into https://realm.io/docs/java/latest/#android-studio-debugging and before you send a managed RealmObject through a reflection-based JSON serializer, you should call
realm.copyFromRealm(obj).