Does Realm models actually require getters and setters? - android

I cannot find it clearly documented anywhere if getters and setters are actually required for fields in a Realm Model. For example, the documentation at https://realm.io/docs/java/latest/api/io/realm/RealmObject.html says
The only restriction a RealmObject has is that fields are not allowed
to be final, transient' or volatile. Any method as well as public
fields are allowed. When providing custom constructors, a public
constructor with no arguments must be declared and be empty.
Fields annotated with Ignore don't have these restrictions and don't
require either a getter or setter.
Which seems to hint that it is required with getters and setters for non-ignored fields. Yet, the documentation at https://realm.io/docs/java/latest/#customizing-objects says
It is possible to use RealmObjects almost like POJOs. Extending from
RealmObject, you can let the fields be public, and use simple
assignments instead of setters and getter.
and then show the code for a Realm Model that does not have any getters and setters and instead have public fields we should use. Really? I thought Realm didn't even store any values in the actual fields, so reading and writing from them is probably a bad idea? I mean their debugging docs https://realm.io/docs/java/latest/#debugging state:
Unfortunately these values are wrong because the field values are not
used. Realm creates a proxy object behind the scenes and overrides the
getters and setters in order to access the persisted data in the Realm
So could someone please enlighten me? Can I skip getters and setters and just stick with public fields? Is there any thorough docs on this?

public fields work in most cases, and since Realm 2.0.0 they work even in constructors of RealmObjects (allowing "default values"), and work if you directly access the property.
For example,
SomeObject obj = results.get(i);
obj.blah = "Blahblah";
That works, because managed RealmObjects' field access are transformed by the Realm-Transformer into proxy getter/setter calls (in this case, into the realmSet$blah method).
This has been the case since 0.88.0, when Realm started being provided as a Gradle plugin.
However, a major limitation is that the proxy field access doesn't run in instrumentation tests, because the androidTestCompile scope does not run the transformer.

Related

Android Room: #Ignore vs Transient

Are those two interchangable in context of Room database entity, or, if not, what are the differences between them?
#Ignore is a Room-specific annotation, saying that Room should ignore that field or method.
transient is a Java construct, indicating that this field should not be serialized in standard Java serialization. Room happens to treat this similarly to #Ignore by default. Mostly, that is there for cases where you are inheriting from some class that happens to use transient and you do not control that class (e.g., it is from a library).
For your own code, if you are not using Java serialization, I recommend sticking with #Ignore for the fields. transient is not an available keyword for a method, so to tell Room to ignore certain constructors, you have no choice but to use #Ignore.
Adding to CommonsWare's answer
transient is not good option for ignoring fields for Room as CommonsWare answered. It will create blocker when same modal is being used to parse data from server and store into database.
Let's assume you have a modal class MyModal.java as below
public static class MyModal {
#SerializedName(“intField”)
public int intField;
#SerializedName(“strField”)
public String strField;
#SerializedName(“booleanField”)
public boolean booleanField;
}
If you want to NOT SAVE booleanField into database, and if you modified that field as
transient : It will ignore this field while saving into database, BUT it will also ignore this field while parsing data which comes from server.
#Ignore : It will only ignore this field while inserting data into database, but this field will participate into json parsing.

Firebase database android getter for property

Firebase documentation for android reads:
The class must define public getters for the properties to be
assigned. Properties without a public getter will be set to their
default value when an instance is deserialized
Why are getters neccessary to assign properties in deserialization?
firebaser here
The JSON serializer/deserializer in the Firebase Android SDK builds a list of candidate properties for a class based on its public fields and its JavaBean-style pseudo-properties that have a getter and a setter.
We've discussed whether the latter should be based solely on a getter for serializing to JSON and a setter for deserializing from JSON. But at this moment that would be a breaking change to the behavior, which we're not willing to do.
If you'd like broader support over the serialization/deserialization you can always use Jackson to do so. See my answer here: How to deserialise a subclass in Firebase using getValue(Subclass.class)

How to configure lint to ignore specific cases?

Sometimes lint produces false warnins if field is operated via bunch of annotations. For a common example:
#SerializedName("id") #Expose private Integer id;
field id is assigned only via gson.fromJson(). Such operation is invisible for lint, thus it throws warning variable id is never assigned
So I want to configure lint, in this particular case, to ignore checks if field is ever assigned, if it is annotated with #SearializedName (please dont suggest raw #SuppressWarnings("unused") which has to be set manualy for every field and will block checks, if field is ever used)
Gson serialises fields using reflection, which takes place at runtime. That UnusedAssignment inspection finds variables which meet any of the following criteria:
the variable never gets read after assignment
the value is always overwritten with another assignment before the next variable read
the variable initializer is redundant (for one of the above two reasons) - the variable is never used.
Your only option to get rid of warnings for this specific inspection is to suppress them, either by updating your lint.xml, or via #SuppressWarnings("unused"). If you really don't want to do either of those things, then it may be possible to write a custom Lint inspection that ignores fields with a #SerializedName annotation.
The disadvantage of this approach is if you want to use #SerializedName in a class that isn't serialised by Gson, you will no longer get a warning if a variable is unused. It is also much more complicated than adding #SuppressWarnings("unused") to the top of your GSON model classes.

How to use satyan's Sugar ORM with #Table annotation

Im very statisfied with SugarOrm for Android, but I ran into an issue. I'm using it with GSON for Json serializations and I want to get rid of SugarRecord's id attribute. I know I should use #Table annotation and later exclude specific field from serialization using #Expose, but after annotating class with #Table I cannot use .save(), delete(),... methods on the object, as it is the case extending SugarRecord. I don't know how to persist objects using #Table annotation.
I found the documentation here very limited.
The document hasn't been updated for the annotation based persistence yet. The methods save(), delete() will be available as static methods on SugarRecord class.
So instead of doing this:
object.save()
You'd be doing this:
SugarRecord.save(object)
Check out some tests here to understand better.
https://github.com/satyan/sugar/tree/master/example/src/test/java/com/example/sugartest

RoboGuice injection of POJOs into POJOs

My Guice is a little rusty (been 3 years) so bear with me. I have a custom API (#ContextSingleton) object that I need to #Inject into my various classes. This works fine when the target class extends from RoboActivity (or in my case, RoboSherlockActivity). However, when I want to inject it into a POJO, the injection fails and I get a null object.
Am I missing anything here? I tried writing a custom Provider for the API object (returning a new Api()), but the object creation graph isn't complete as any #Inject members within the API object is still null.
Right now I'm working around this by passing in the API object into POJOs instead of injecting it, but I'd like to eventually use #Inject for consistency.
I have this question, too. I think that we need to just use regular Guice for POJO cases. See my answer here: https://stackoverflow.com/a/24671352/189341

Categories

Resources