I am using Realm as a data module in my android application, though I am running into some problems regarding how to assign custom methods to Realm objects.
EDIT: Realm 0.88.0 has enabled the usage of custom methods, and you can also implement interfaces with your Realm Objects. But I'm keeping my repository pattern that was the original answer below. Latest version at the time of writing is 0.88.1.
I firmly believe that data
objects should only contain data, and the logic should be separate.
public interface RealmRepository<T extends RealmObject, ID extends Serializable> {
T findOne(Realm realm, ID id);
RealmResults<T> findAll(Realm realm);
void insertOrUpdate(Realm realm, T t);
void insertOrUpdate(Realm realm, Collection<T> t);
T saveOrUpdate(Realm realm, T t);
RealmList<T> saveOrUpdate(Realm realm, RealmList<T> tList);
RealmQuery<T> query(Realm realm);
void delete(Realm realm, ID id);
void delete(Realm realm, T t);
void deleteAll(Realm realm, RealmResults<T> realmResults);
void deleteEveryObject(Realm realm);
long count(Realm realm);
}
And
public abstract class BaseRealmRepositoryImpl<T extends RealmObject, ID extends Serializable>
implements RealmRepository<T, ID> {
protected Class<T> clazz;
public BaseRealmRepositoryImpl(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public RealmResults<T> findAll(Realm realm) {
return query().findAll();
}
@Override
public void insertOrUpdate(Realm realm, T t) {
realm.insertOrUpdate(t);
}
@Override
public void insertOrUpdate(Realm realm, Collection<T> collection) {
realm.insertOrUpdate(collection);
}
@Override
public T saveOrUpdate(Realm realm, T t) {
return realm.copyToRealmOrUpdate(t);
}
@Override
public RealmList<T> saveOrUpdate(Realm realm, RealmList<T> list) {
RealmList<T> realmList = new RealmList<>();
for(T t : realm.copyToRealmOrUpdate(list)) {
realmList.add(t);
}
return realmList;
}
@Override
public RealmQuery<T> query(Realm realm) {
return realm.where(clazz);
}
@Override
public void deleteEveryObject(Realm realm) {
realm.delete(clazz);
}
@Override
public void delete(Realm realm, T t) {
t.deleteFromRealm();
}
@Override
public void deleteAll(Realm realm, RealmResults<T> realmResults) {
realmResults.deleteAllFromRealm();
}
@Override
public long count(Realm realm) {
return query().count();
}
}
And
public abstract class StringRealmRepositoryImpl<T extends RealmObject>
extends BaseRealmRepositoryImpl<T, String>
implements RealmRepository<T, String> {
public StringRealmRepositoryImpl(Class<T> clazz) {
super(clazz);
}
@Override
public T findOne(Realm realm, String id) {
return query(realm).equalTo(getIdFieldName(), id).findFirst();
}
@Override
public void delete(Realm realm, String id) {
delete(realm, findOne(realm, id));
}
}
And
public class TeacherRealm extends RealmObject {
@PrimaryKey
private String id;
//getter, setter, etc.
}
And
public class TeacherRepositoryImpl
extends StringRealmRepositoryImpl<TeacherRealm>
implements TeacherRepository {
public TeacherRepositoryImpl() {
super(TeacherRealm.class);
}
}
And repositories are extensible.
I'm working through a similar question. My approach is going to be to use static 'helper' methods to achieve all additional logic. Passing an instance of my object type in the method call.
I have the same situation to find a work around for custom logic in realmObjects.
I abused the builder pattern for a comfortable way.
Example:
public class Information extends RealmObject {
@PrimaryKey
private String id;
private int value;
private String text;
//getter and setter for id, value and text
//Helps to create and commit a information realm object
public static class Create {
private Realm realm;
private Information information;
public Create() {
this.realm = Realm.getDefaultInstance();
this.realm.beginTransaction();
this.information = realm.createObject(Information.class);
//init realmObject with defauls
this.information.setId(UUID.randomUUID().toString());
this.information.setValue(0);
this.information.setText("");
//space for additional logic
}
public Create setValue(int val) {
this.information.setValue(val);
//space for additional logic
return this;
}
public Create setText(String s) {
this.information.setText(s);
//space for additional logic
return this;
}
public Information commit() {
//space for additional logic
this.realm.commitTransaction();
return this.information;
}
}
//Helps to modify and commit a information realm object
public static class Modify {
private Realm realm;
private Information information;
public Modify(Information information) {
this.realm = Realm.getDefaultInstance();
this.information = information;
this.realm.beginTransaction();
}
public Modify setValue(int val) {
this.information.setValue(val);
//space for additional logic
return this;
}
public Modify setText(String s) {
this.information.setText(s);
//space for additional logic
return this;
}
public void commit() {
//space for additional logic
this.realm.commitTransaction();
}
}
}
How to use
//create a reamlobject
Information info = new Information.Create()
.setText("Hello World");
.commit();
//modify the created info object
new Information.Modify(info)
.setValue(1)
.commit();