Realm throws the following error message if you have a custom constructor within the Realm model class.
Class <class name> must declare a public constructor with no arguments if it contains custom constructors
Below is the Realm model class.
#RealmClass
public class User implements RealmModel {
public User(Integer id, String email) {
this.id = id;
this.email = email;
}
How do you get rid of it?
Realm requires every Realm model class to have a public constructor with no arguments. This is because of the method createObject(Class<E> clazz). For example, to get the User class to work, it'd look like the following.
#RealmClass
public class User implements RealmModel {
public User() {
}
public User(Integer id, String email) {
this.id = id;
this.email = email;
}
Related
I'm having a problem with building Realm object which has a custom class.
#Parcel(
value = Parcel.Serialization.BEAN,
analyze = { Message.class })
#RealmClass
public class Message implements Comparable<Message>, RealmModel {`
#PrimaryKey
#Index
private long id;
#JsonProperty("thread_id")
long threadId;
#JsonProperty("message")
public String message;
#JsonProperty("user")
public User user;
...
}
When server send json response, try to parse as Message realm object with
realm.createObjectFromJson(MesssageMessage.class, JSONObject)
The problem is User. I've got an compile error "Filed user is not supported".
Below is the User class which is not realm object.
#JsonIgnoreProperties("incomplete_signed_up")
public class User implements KeepClassFromProguard, Parcelable {
public static final Parcelable.Creator<User> CREATOR = new
Parcelable.Creator<User>() {
#Override
public User createFromParcel(Parcel in) {
return new User(in);
}
#Override
public User[] newArray(int size) {
return new User[size];
}
};
public long id;
#JsonProperty("account_id")
private long accountId;
#JsonProperty("display_name")
public String display_name;
#JsonProperty("nick_name")
public String nickname;
#JsonProperty("user_detail")
public UserDetail userDetail;
...
}
I read https://gist.github.com/cmelchior/ddac8efd018123a1e53a and http://parceler.org/#getting_parceler, but I could't get answer yet.
I can't change every class to realm object because they all have another custom classes.
Does anyone know how this is handled? Hope there is any good example.
Thanks.
All references in a RealmModel must reference other RealmModel classes. This is the only way we can persist them.
You can #Ignore the user field, but then it will not be saved by Realm.
I'm having an issue when I try to call addAll() on RealmList<Tile> with accounts which are already stored in realm file.
realmList.addAll(tiles) is called based on a response from an API call which may return Tiles containing one ore more accounts already stored in realm. The object return by the API looks like the one below:
public class ActivityStreamData extends RealmObject {
#PrimaryKey
private long id = DB_ID;
public String timestamp;
public RealmList<Tile> activity = new RealmList<>();
public MessageListMeta metadata = new MessageListMeta();
}
public class Tile extends RealmObject {
public String type;
public RealmList<Account> accounts;
public Account account;
}
public class Account extends RealmObject {
#PrimaryKey
public long id;
public String timestamp;
public String name;
public String email;
}
The call fails when trying to add tiles to the activityStream.activity list when fetching more.
Any way to force addAll to act as a createOrUpdate call
I have data in my firebase DB, everything works fine until I try to De-serialize the data.
Error: argument 1 has type io.realm.RealmList, got java.util.ArrayList
Here's my code:
DatabaseReference root = FirebaseDatabase.getInstance().
getReferenceFromUrl("https://swing-8792d.firebaseio.com/playlist");
Query playlistQuery = root.orderByKey().equalTo(key);
playlistQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
Log.d("Child", child + "");
Playlist receivedPlaylist = child.getValue(Playlist.class);
Playlist playlist = new Playlist();
playlist.setCreatedBy(receivedPlaylist.getCreatedBy());
playlist.setName(receivedPlaylist.getName());
playlist.setMyMap(receivedPlaylist.getMyMap());
playlist.setQrKey(receivedPlaylist.getQrKey());
playlist.setCount(receivedPlaylist.getCount());
playlist.setId(receivedPlaylist.getId());
playlist.setTracks(receivedPlaylist.getTracks());
mPlaylist.add(playlist);
}
This is my POJO class:
#RealmClass
public class Playlist extends RealmObject {
String name;
Long id;
RealmList<Track> tracks;
Integer count;
String createdBy;
RealmList<UserMap> myMap;
String qrKey;
public RealmList<UserMap> getMyMap() {
return myMap;
}
public void setMyMap(RealmList<UserMap> myMap) {
this.myMap = myMap;
}
public Playlist(){}
public String getQrKey() {
return qrKey;
}
public void setQrKey(String qrKey) {
this.qrKey = qrKey;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public RealmList<Track> getTracks() {
return tracks;
}
public void setTracks(RealmList<Track> tracks) {
this.tracks = tracks;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
If I try to de-serialize with Normal POJO class (i.e Removing Realm) it works fine.
Firebase won't work with classes that do not have default constructor or private variables i.e no public getter/setter.
A easier solution in your case would be to make a middleware class that is the same pojo just not extending RealmObject. Next initialise your RealmObject subclass using the values of the pojo.
Pseudo code
class SimplePojoPlaylist {
public String variable;
}
class Playlist extends RealmObject {
public String variable;
}
Then first cast into SimplePojoPlaylist
for (DataSnapshot child : dataSnapshot.getChildren()) {
SimplePojoPlaylist receivedPlaylist = child.getValue(SimplePojoPlaylist.class);
Playlist playList = new Playlist();
playList.variable = receivedPlaylist.variable;
}
RealmList is not a supported type for deserialization. Your database checks its structure and deduces that tracks should be an ArrayList. Then, when it tries to convert it, it finds that the types do not match.
Check this link from the docs:
Also, it is a good practice to make your objects immutable to avoid unwanted access and/or modifications.
Creating an empty object from scratch and then calling setter methods to define its state is not a very good pattern, because it can create a situation where an object is accessed before when its state is "broken".
If you need to create an object that is flexible, has a few mandatory fields and some optional, consider using the Builder pattern, although to do it you'd have to redesign your model.
wikipedia - Builder
If you don't need/want to use a builder, my advice is:
1) Make the empty constructor private and create another public one that requires all the fields.
2) Change your tracks field to be of type "List". Then, if you need the object to return a RealmList create another getter method such as tracksAsRealmList() that makes a RealmList out of the member list and returns it.
3) Make sure that the "Track" model has an empty private constructor, a public one with all of its parameters and that all of its fields are supported by firebase deserialization.
4) Unless strictly necessary, make your object fields private and set its value through a setter method.
I hope this helps you.
I have data in my firebase DB, everything works fine until I try to De-serialize the data.
Error: argument 1 has type io.realm.RealmList, got java.util.ArrayList
Here's my code:
DatabaseReference root = FirebaseDatabase.getInstance().
getReferenceFromUrl("https://swing-8792d.firebaseio.com/playlist");
Query playlistQuery = root.orderByKey().equalTo(key);
playlistQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
Log.d("Child", child + "");
Playlist receivedPlaylist = child.getValue(Playlist.class);
Playlist playlist = new Playlist();
playlist.setCreatedBy(receivedPlaylist.getCreatedBy());
playlist.setName(receivedPlaylist.getName());
playlist.setMyMap(receivedPlaylist.getMyMap());
playlist.setQrKey(receivedPlaylist.getQrKey());
playlist.setCount(receivedPlaylist.getCount());
playlist.setId(receivedPlaylist.getId());
playlist.setTracks(receivedPlaylist.getTracks());
mPlaylist.add(playlist);
}
This is my POJO class:
#RealmClass
public class Playlist extends RealmObject {
String name;
Long id;
RealmList<Track> tracks;
Integer count;
String createdBy;
RealmList<UserMap> myMap;
String qrKey;
public RealmList<UserMap> getMyMap() {
return myMap;
}
public void setMyMap(RealmList<UserMap> myMap) {
this.myMap = myMap;
}
public Playlist(){}
public String getQrKey() {
return qrKey;
}
public void setQrKey(String qrKey) {
this.qrKey = qrKey;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public RealmList<Track> getTracks() {
return tracks;
}
public void setTracks(RealmList<Track> tracks) {
this.tracks = tracks;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
If I try to de-serialize with Normal POJO class (i.e Removing Realm) it works fine.
Firebase won't work with classes that do not have default constructor or private variables i.e no public getter/setter.
A easier solution in your case would be to make a middleware class that is the same pojo just not extending RealmObject. Next initialise your RealmObject subclass using the values of the pojo.
Pseudo code
class SimplePojoPlaylist {
public String variable;
}
class Playlist extends RealmObject {
public String variable;
}
Then first cast into SimplePojoPlaylist
for (DataSnapshot child : dataSnapshot.getChildren()) {
SimplePojoPlaylist receivedPlaylist = child.getValue(SimplePojoPlaylist.class);
Playlist playList = new Playlist();
playList.variable = receivedPlaylist.variable;
}
RealmList is not a supported type for deserialization. Your database checks its structure and deduces that tracks should be an ArrayList. Then, when it tries to convert it, it finds that the types do not match.
Check this link from the docs:
Also, it is a good practice to make your objects immutable to avoid unwanted access and/or modifications.
Creating an empty object from scratch and then calling setter methods to define its state is not a very good pattern, because it can create a situation where an object is accessed before when its state is "broken".
If you need to create an object that is flexible, has a few mandatory fields and some optional, consider using the Builder pattern, although to do it you'd have to redesign your model.
wikipedia - Builder
If you don't need/want to use a builder, my advice is:
1) Make the empty constructor private and create another public one that requires all the fields.
2) Change your tracks field to be of type "List". Then, if you need the object to return a RealmList create another getter method such as tracksAsRealmList() that makes a RealmList out of the member list and returns it.
3) Make sure that the "Track" model has an empty private constructor, a public one with all of its parameters and that all of its fields are supported by firebase deserialization.
4) Unless strictly necessary, make your object fields private and set its value through a setter method.
I hope this helps you.
I need to integrate Realm database in my eclipse JUNO(Android Development Tool). I used realm 0.81.1 version. I had include all library files in my android project lib folder and configured realm-0.81.1.jar in buildpath.when "java.lang.IlleagaArgumentException:User is not part of the schema for this realmrun my project it throws error ".
Here User is an class that extends RealmObject.
The User class code is given below:
public class User extends RealmObject {
#PrimaryKey
private String name;
private int age;
#Ignore
private int sessionId;
// Standard getters & setters generated by your IDEā¦
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getSessionId() { return sessionId; }
public void setSessionId(int dontPersist) { this.sessionId = sessionId; }
}
The error is produced when executing the following code:
Realm realm = Realm.getInstance(this);
realm.beginTransaction();
User user = realm.createObject(User.class);
user.setName("Jhon");
user.setAge(10);
realm.commitTransaction();
Please give me suggestion to work with Realm Database
Thanks in advance.
As you are using Eclipse you need to add the #RealmClass annotation manually as it doesn't support inherited annotations. So you model class must look like this:
#RealmClass
public class User extends RealmObject
{
// ...
}
Try this and let me know if it works. Thanks.