-
-
Save carloseduardosx/6c3a3dfc3a9cb467aa464884f39544c2 to your computer and use it in GitHub Desktop.
package com.carloseduardo.model; | |
import com.carloseduardo.constants.KnownClasses; | |
import com.carloseduardo.exception.UnknownModelException; | |
import io.realm.RealmObject; | |
import io.realm.annotations.PrimaryKey; | |
import io.realm.annotations.Required; | |
/** | |
* @author Carlos Eduardo | |
* @since 03/09/2016 | |
*/ | |
public class AutoIncrementEntity extends RealmObject { | |
@Required | |
@PrimaryKey | |
private Integer _id = 1; | |
private Integer accountType; | |
private Integer equipment; | |
private Integer location; | |
public Integer getId() { | |
return _id; | |
} | |
public Integer getAccountType() { | |
return accountType; | |
} | |
public void setAccountType(Integer accountType) { | |
this.accountType = accountType; | |
} | |
public Integer getEquipment() { | |
return equipment; | |
} | |
public void setEquipment(Integer equipment) { | |
this.equipment = equipment; | |
} | |
public Integer getLocation() { | |
return location; | |
} | |
public void setLocation(Integer location) { | |
this.location = location; | |
} | |
public void incrementByClassName(String className) { | |
switch (className) { | |
case KnownClasses.ACCOUNT_TYPE: | |
accountType = accountType == null ? 1 : ++accountType; | |
break; | |
case KnownClasses.EQUIPMENT: | |
equipment = equipment == null ? 1 : ++equipment; | |
break; | |
case KnownClasses.LOCATION: | |
location = location == null ? 1 : ++location; | |
break; | |
default: | |
throw new UnknownModelException("Class name: " + className); | |
} | |
} | |
public Integer findByClassName(String className) { | |
switch (className) { | |
case KnownClasses.ACCOUNT_TYPE: | |
return this.accountType; | |
case KnownClasses.EQUIPMENT: | |
return this.equipment; | |
case KnownClasses.LOCATION: | |
return this.location; | |
default: | |
throw new UnknownModelException("Class name: " + className); | |
} | |
} | |
} |
package com.carloseduardo.application; | |
import android.app.Application; | |
import android.content.Context; | |
import io.realm.Realm; | |
import io.realm.RealmConfiguration; | |
/** | |
* @author Carlos Eduardo | |
* @since 03/09/2016 | |
*/ | |
public class CustomApplication extends Application { | |
private static CustomApplication application; | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
application = this; | |
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder() | |
.deleteRealmIfMigrationNeeded() | |
.build(); | |
Realm.setDefaultConfiguration(realmConfiguration); | |
} | |
public static CustomApplication getApplication() { | |
return application; | |
} | |
public static Context getContext() { | |
return application; | |
} | |
} |
package com.carloseduardo.constants; | |
/** | |
* @author Carlos Eduardo | |
* @since 03/09/2016 | |
*/ | |
public interface KnownClasses { | |
String ACCOUNT_TYPE = "AccountType"; | |
String EQUIPMENT = "Equipment"; | |
String LOCATION = "Location"; | |
} |
package com.carloseduardo.database; | |
import android.support.annotation.NonNull; | |
import android.util.Log; | |
import com.carloseduardo.application.CustomApplication; | |
import com.carloseduardo.model.AutoIncrementEntity; | |
import io.realm.Realm; | |
import io.realm.RealmConfiguration; | |
import io.realm.RealmObject; | |
/** | |
* Simple implementation of Auto Increment feature for Realm | |
* | |
* RealmAutoIncrement is a singleton which maintain the last id saved from each model. | |
* <p/> | |
* To get next id from anyone model, simple call the method getNextIdFromModel. | |
* | |
* @see #getNextIdFromModel(Class) | |
* | |
* @author Carlos Eduardo | |
* @since 03/09/2016 | |
*/ | |
public final class RealmAutoIncrement { | |
private static RealmAutoIncrement autoIncrementMap; | |
private RealmAutoIncrement() { | |
createAutoIncrementEntityIfNotExist(); | |
} | |
/** | |
* Search in AutoIncrementEntity for the last saved id from model passed and return the next one | |
* | |
* @param clazz Model which should get the next id | |
* @return The next id which can be saved in database | |
*/ | |
public Integer getNextIdFromModel(Class<? extends RealmObject> clazz) { | |
if (isValidMethodCall()) { | |
Integer id = updateIdByClassName(clazz); | |
Log.i("RealmAutoIncrement", "getNextIdFromModel: " + id); | |
return id; | |
} | |
Log.e("RealmAutoIncrement", "getNextIdFromModel is called by a not valid method"); | |
return null; | |
} | |
private Integer updateIdByClassName(final Class<? extends RealmObject> clazz) { | |
Realm realm = getRealm(); | |
final AutoIncrementEntity autoIncrementEntity = realm.where(AutoIncrementEntity.class).findFirst(); | |
if (realm.isInTransaction()) { | |
autoIncrementEntity.incrementByClassName(clazz.getSimpleName()); | |
realm.copyToRealmOrUpdate(autoIncrementEntity); | |
} else { | |
realm.executeTransaction(new Realm.Transaction() { | |
@Override | |
public void execute(Realm realm) { | |
autoIncrementEntity.incrementByClassName(clazz.getSimpleName()); | |
realm.copyToRealmOrUpdate(autoIncrementEntity); | |
} | |
}); | |
} | |
return autoIncrementEntity.findByClassName(clazz.getSimpleName()); | |
} | |
/** | |
* Utility method to validate if the method is called from reflection, | |
* in this case is considered a not valid call otherwise is a valid call | |
* | |
* @return The boolean which define if the method call is valid or not | |
*/ | |
private boolean isValidMethodCall() { | |
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); | |
for (StackTraceElement stackTraceElement : stackTraceElements) { | |
if (stackTraceElement.getMethodName().equals("newInstance")) { | |
return false; | |
} | |
} | |
return true; | |
} | |
private void createAutoIncrementEntityIfNotExist() { | |
AutoIncrementEntity autoIncrementEntity = getRealm().where(AutoIncrementEntity.class).findFirst(); | |
if (autoIncrementEntity == null) { | |
createAutoIncrementEntity(); | |
} | |
} | |
private void createAutoIncrementEntity() { | |
getRealm().executeTransaction(new Realm.Transaction() { | |
@Override | |
public void execute(Realm realm) { | |
AutoIncrementEntity autoIncrementEntity = new AutoIncrementEntity(); | |
realm.copyToRealm(autoIncrementEntity); | |
} | |
}); | |
} | |
private Realm getRealm() { | |
return Realm.getInstance(getRealmConfiguration()); | |
} | |
@NonNull | |
private RealmConfiguration getRealmConfiguration() { | |
//TODO Change for your current RealmConfiguration | |
return new RealmConfiguration.Builder() | |
.deleteRealmIfMigrationNeeded() | |
.build(); | |
} | |
public static RealmAutoIncrement getInstance() { | |
if (autoIncrementMap == null) { | |
autoIncrementMap = new RealmAutoIncrement(); | |
} | |
return autoIncrementMap; | |
} | |
} |
package com.carloseduardo.exception; | |
/** | |
* @author Carlos Eduardo | |
* @since 03/09/2016 | |
*/ | |
public class UnknownModelException extends RuntimeException { | |
public UnknownModelException() { | |
} | |
public UnknownModelException(String message) { | |
super(message); | |
} | |
} |
Hi, thanks for this gist. I've a problem: when I try to use this class I obtain the error: getNextIdFromModel is called by a not valid method. My object is created with this code:
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Task newTask = realm.createObject(Task.class);
newTask.setTitle(taskTitleInput.getText().toString());
}
}
The Task class:
public class Task extends RealmObject {
public static final String TITLE = "title";
@Required
@PrimaryKey
private Integer _id = RealmAutoIncrement.getInstance().getNextIdFromModel(Task.class);
@Required
private String title;
private String description;
private boolean isCompleted;
private Date dueDate;
public Task() {}
public Task(String title, String description, Date dueDate) {
this.title = title;
this.description = description;
this.isCompleted = false;
this.dueDate = dueDate;
}
public Integer getId() {
return _id;
}
Thanks
It seems that it's not a problem; I obtain that message only when my activity reads the content of the realm db.
Apologize for the delay @eloquentbit. That message is because Realm create a new instance of your model by reflection when he's persisting your data. In this case the AutoIncrementEntity shouldn't increment the model id
Hi bro, you should update Realm Configuration, in your file RealmAutoIncrement remplace this line : return new RealmConfiguration.Builder(CustomApplication.getContext()) .deleteRealmIfMigrationNeeded() .build();
by this new line return new RealmConfiguration.Builder() .deleteRealmIfMigrationNeeded() .build();
and do the same thing in your Application's class.
Also, you should update @Required @PrimaryKey private Integer _id = RealmAutoIncrement.getInstance().getNextIdFromDomain(AccountType.class);
it becomes getNextIdFromModel not getNextIdFromDomain
Thanks for the update @IvanovE.
Sample of how to use the RealmAutoIncrement
Change the RealmAutoIncrement.getRealmConfiguration() to return your own configuration.
NOTE: ClassName declared in the interface KnownClasses should have the same name of the referenced class.