0

I have a custom object named User, which is a RealmObject. This object also has annotations for Moshi because I plan on using this object in a retrofit call.

public class User extends RealmObject
{
    @PrimaryKey private long id;
    @Json(name = "email") private String email;
    @Json(name = "first_name") private String firstName;
    @Json(name = "last_name") private String lastName;
    @Json(name = "password_hash") private String passwordHash;
    @Json(name = "avatar") private String avatar;
    @Json(name = "phone_number") private String phoneNumber;
    @Json(name = "country") private String country;
    @Json(name = "city") private String city;
    @Json(name = "address") private String address;
    @Json(name = "location") private Location location;
    @Json(name = "zip") private String zip;
    @Json(name = "device_meta") private DeviceMeta deviceMeta;
}

When I query my Realm DB for a user like this:

User user = getRealm().where(User.class).findFirst();

I get this response (using debugging):

Realm Object

As can be seen, the object isn't initialized but the values are showing in the first line.

What is the issue here?

When I pass the above object as a @Body parameter, it appears to be empty.

I've also checked via Fiddler and the request sent to the server contains an empty object.

Question: How do I get this object to get the proper values?

Asim
  • 6,962
  • 8
  • 38
  • 61

2 Answers2

2

It likely has the proper values assuming you're saving and querying correctly. Realm creates a subclassed version of each extended RealmObject as a "RealmProxy" object, and sometimes the in the debugger it doesn't look like what you would expect. You'll notice that your class is actually showing up as UserRealmProxy (but it's inline values aren't null after User = ...).

To view the non-realm proxy version, you would have to use Realm.copyFromRealm(...).

Also, note that anything parsed from the network won't be added to Realm automatically -- you have to explicitly copy to realm in this case to get the values on later queries, since things parsed in from the network are unmanaged initially.

Submersed
  • 8,810
  • 2
  • 30
  • 38
  • Thanks a ton for your reply. You've solved my problem. copyFromRealm properly initialized the values in my object. – Asim Jan 31 '18 at 20:34
  • Glad it helped! – Submersed Jan 31 '18 at 20:36
  • Done. I'm curious about how this works (even after reading a very detailed answer here on stack). If I call the getters, I get proper values. But if I pass the same object to retrofit, it is unable to get any values out of it. Does retrofit use some other method to access values? – Asim Jan 31 '18 at 20:37
  • Might be worth opening up a separate question on that detailing it more specifically, since you'd need to provide more around your implementation details for the retrofit request. In my experience, I haven't had any issues using managed/unmanaged objects interchangeably in your described use-case. It could potentially be an issue around how moshi is serializing on the subclass because of the annotations, but I use Gson generally so I'd have to dive deeper. – Submersed Jan 31 '18 at 20:41
  • Moshi has Reflection to read the values directly from the fields, but managed RealmProxy classes only read the data when you call an accessor – EpicPandaForce Jan 31 '18 at 20:44
  • Thanks for the explanation. Reflection is why Moshi fails to get anything out of a RealmObject. – Asim Jan 31 '18 at 21:40
2

Please reconsider this design.

Using the same types for local persistence and networking saves some boilerplate code. As your application grows in complexity this approach may become quite fragile.

Creating a basic value object, UserJson, and a JSON adapter to map between is not much code. With Moshi’s @ToJson/@FromJson methods it's also quite easy and even testable. This will give you lots of flexibility in the future.

Jesse Wilson
  • 39,078
  • 8
  • 121
  • 128
  • Thanks for the tip. You're suggest separate objects for Realm and Moshi? And then using toJson on the result I obtain from Realm? – Asim Feb 01 '18 at 20:29
  • You can use a separate object to represent the JSON model, but get Moshi to automatically convert into your preferred Realm type using it's adapter methods feature. – Jesse Wilson Feb 02 '18 at 21:25