I have a Realm object "TaskEntity" which has RealmList field.
public class TaskEntity extends RealmObject {
...
private RealmList<ContextEntity> contexts;
}
I make new instance of this entity through constructor and copy values of fields from Realm object.
TaskEntity task = mRealm.where(TaskEntity.class).findFirst();
TaskEntity newTask = new TaskEntity();
newTask.setId(task.getId());
newTask.setName(task.getName());
newTask.setContexts(task.getContexts()); //copying of RealmList
When user makes some changes and wants to save it I call copyToRealmOrUpdate.
mRealm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mRealm.copyToRealmOrUpdate(newTask);
}
});
Sometimes old state has several items in RealmList and user doesn't make changes in that field. So when I call copyToRealmOrUpdate, RealmList becomes empty.
newTask.getContexts().size(); // 2 items
mRealm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mRealm.copyToRealmOrUpdate(newTask);
}
});
newTask.getContexts().size(); // 0 items
How can I fix it?
Related
I have a messaging application which uses RealmDB to store messages and threads for users. The message threads are RealmObjects. I'm trying to figure out how to add a RealmChangeListener which will trigger when any of the threads are updated (i.e a new message is received). The threads are initially retrieved and subsequently updated from my MessageThreadList activity via a syncMessages function in the API. It seems like no matter where I try to add the listener I get the
Cannot add listener from unmanaged object
error.
My code:
MessageThread.java
public class MessageThread extends RealmObject {
//Some member variables here - Id, title, etc
//This is the field that would indicate a new message if changed
private Date mLatestSentTimeStamp;
//Empty constructor
public MessageThread() { }
public MessageThread(JSONObject jsonOb) {
//Filling fields from JSON here
}
}
ThreadListActivity.java
public class ThreadListActivity {
private Realm realm;
#Override
public void onCreate() {
Realm.init();
realm = Realm.getDefaultInstance();
MyAPI.syncMessages();
}
MyAPI.java
static protected void syncMessages() {
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
JSONArray jsonMsgThreads = getJSONFromServer();
for (int i = 0; i < jsonMsgThreads.length(); i++) {
MessageThread m = new MessageThread(jsonMsgThreads.getJSONObject(i));
realm.copyToRealmOrUpdate(m);
}
realm.commitTransaction();
}
If it's not possible to add it anywhere here, is there anything that I could do to have a listener on each MessageThread?
public class ThreadListActivity {
private Realm realm;
private RealmResults<MessageThread> messageThreads;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
Realm.init(this);
realm = Realm.getDefaultInstance();
messageThreads = realm.where(MessageThread.class).findAll();
messageThreads.addChangeListener((results) -> {
// any message thread was modified
}
MyAPI.syncMessages();
}
I'm running in to an issue where I delete a RealmObject (and confirm its gone using StethoRealm), but when I create and save a new RealmObject with the same variable value, the deleted RealmObject reappears along with my new RealmObject.
With the below object - I delete the myObject1 by matching the 'id', but when I create a new MyObject myObject2 with the same 'name' both objects appear in my realm
Any tips on why this might be happening?
Example:
public class MyObject extends RealmObject {
#PrimaryKey
private String id;
private String name;
// getters and setters
}
Edit
Delete call
#Override
public void deleteMyObjectById(final String id, final OnDeleteMyObjectById callback) {
Realm realm = new MyRealmConfiguration().getDefaultRealm();
final RealmResults<MyObject> myObjects = realm.where(MyObject.class).equalTo(RealmTable.MyObject.ID, id).findAll();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
myObjects.deleteAllFromRealm();
if (callback != null) {
callback.onSuccess();
}
}
});
realm.close();
}
Add call
#Override
public void addMyObject(MyObject myObject, OnSaveMyObjectCallback callback) {
Realm realm = new MyRealmConfiguration().getDefaultRealm();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(myObject);
if (callback != null) {
callback.onSuccess();
}
}
});
realm.close();
}
I'm not sure as to how you are deleting your objects. The way I'm deleting them (and it works) is...
final RealmResults<UserCredentials> credentialResults = realm.where(UserCredentials.class).findAll();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
credentialResults.deleteAllFromRealm();
}
});
realm.close();
Of course, you are using MyObject instead of UserCredentials, and you aren't deleting everything of that type, but it should be similar enough. Try using executeTransaction and realm.close() if you aren't already.
Try something like this. get the instance inside transcation method and delete. i have been using this for one of my app. and it works fine with deletion process
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<MyObject> myObjects = realm.where(MyObject.class).equalTo(RealmTable.MyObject.ID, id).findAll();
myObjects.deleteAllFromRealm();
}
});
I am new to realm , my issue is how to add the two different data example(in sql database two different tables are created to add the two diffrent data) like wise how can i add the two data in realm database.
public void addData(final RealmPhoneCallLogs phoneCallLog){
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmPhoneCallLogs phoneCallLogs = realm.createObject(RealmPhoneCallLogs.class);
phoneCallLogs.setId(phoneCallLog.getId());
phoneCallLogs.setStartTime(phoneCallLog.getStartTime());
phoneCallLogs.setActualStartTime(phoneCallLog.getActualStartTime());
phoneCallLogs.setCallDuration(phoneCallLog.getCallDuration());
phoneCallLogs.setCallRecords(phoneCallLog.getCallRecords());
phoneCallLogs.setCallStatus(phoneCallLog.getCallRecords());
phoneCallLogs.setEndTime(phoneCallLog.getEndTime());
phoneCallLogs.setNumber(phoneCallLog.getNumber());
phoneCallLogs.setCallType(phoneCallLog.getCallType());
}
}
);
}
The above data is added into the database.
public void addImportant(final RealmPhoneCallLogs importantPhonecallLog){
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmPhoneCallLogs importantCalls = realm.createObject(RealmPhoneCallLogs.class);
importantCalls.setId(importantPhonecallLog.getId());
importantCalls.setStartTime(importantPhonecallLog.getStartTime());
importantCalls.setActualStartTime(importantPhonecallLog.getActualStartTime());
importantCalls.setCallDuration(importantPhonecallLog.getCallDuration());
importantCalls.setCallRecords(importantPhonecallLog.getCallRecords());
importantCalls.setCallStatus(importantPhonecallLog.getCallRecords());
importantCalls.setEndTime(importantPhonecallLog.getEndTime());
importantCalls.setNumber(importantPhonecallLog.getNumber());
importantCalls.setCallType(importantPhonecallLog.getCallType());
}
});
}
How can i add the data into database.If i add the data means it is added in the existing object created in databse.How can i add this in separate table in database.
I have this classes
class Student extends RealmObject {
public String code;
public String name;
public String email;
public Course course;
}
class Course extends RealmObject {
public String code;
public String name;
}
class Sync {
// ...
// To sync data I am using retrofit, look the method to update course
public void onResponse(Call<...> call, Response<...> response) {
if (response.isSuccessful()) {
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.delete(Course.class);
realm.copyToRealm(response.body());
}
});
}
}
}
After call Sync to update Courses, all Student object has its course setting to null, this is expected behavior after called realm delete?
Even after table is populated again, the course on Student is still null.
Today I made this change on the code:
class Course extends RealmObject {
#PrimaryKey
public String code;
public String name;
}
class Sync {
// ...
// To sync data I am using retrofit, look the method to update course
public void onResponse(Call<...> call, Response<...> response) {
if (response.isSuccessful()) {
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response.body());
}
});
}
}
}
I made this too late to avoid delete the courses.
There is something that can I do to recovery the references courses and set it again to student?
Thank you.
This is expected behavior, because you invalidate the object links by deleting the objects you are pointing to.
To restore them, you would have to set the links again.
Another solution would be to not delete courses that you still need. This would be done if you annotate code with #PrimaryKey, that way you would "update" courses that are already in. Then the problem would be removing courses/students no longer in the response, but there are solutions ready-made for that.
public class Robject extends RealmObject {
#PrimaryKey
private String code;
#Index
private String name;
//...
#Index
private boolean isBeingSaved;
//getters, setters
}
And
// background thread
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
Robject robject = new Robject();
for(Some some : somethings) {
robject.set(some....);
realm.insertOrUpdate(robject);
}
realm.where(Robject.class)
.equalTo(Robject.IS_BEING_SAVED, false) // compile 'dk.ilios:realmfieldnameshelper:1.1.0'
.findAll()
.deleteAllFromRealm(); // delete all non-saved data
for(Robject robject : realm.where(Robject.class).findAll()) { // realm 0.89.0+
robject.setIsBeingSaved(false); // reset all save state
}
}
});
} finally {
if(realm != null) {
realm.close();
}
}
io.realm:realm-gradle-plugin:2.0.0'
Android Studio 2.2.2
I am trying to delete objects from the realm database. The items seems to get deleted. But when I close the app and load items from the database the deleted ones still seem to have a reference to them. This is my code below for deleting.
If the delete onSuccess is called I send back the item to be removed from the recyclerview's adapter. Is this the correct way to do this?
#Override
public void deletePerson(final Person person, final DeleteListener deleteListener) {
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<Person> results = realm.where(Person.class).equalTo("mId", person.getId()).findAll();
results.deleteAllFromRealm();
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
/* send the person object back to be removed from the recyclerview after success*/
deleteListener.onDeleteSuccess(person);
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
deleteListener.onDeleteFailure(error.getMessage());
}
});
}
And when I load the persons the ones that are deleted seem to have a reference in realm and doesn't seem to be completely removed.
#Override
public void loadPersons(final LoadPersonListener loadPersonListener) {
if(mRealm.isClosed()) {
mRealm = Realm.getDefaultInstance();
}
RealmResults<Person> personsList = mRealm.where(Person.class).findAll();
if(personsList.size() > 0) {
loadPersonListener.onLoadPersonSuccess(personsList);
}
else {
loadPersonListener.onLoadPersonFailure("No items in the database");
}
}
You aren't removing anything from the Realm at the moment, you're just querying. Also, you're accessing the Person you sent in on a background thread, which ought to throw IllegalStateException.
So instead of
#Override
public void deletePerson(final Person person, final DeleteListener deleteListener) {
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<Person> results = realm.where(Person.class).equalTo("mId", person.getId()).findAll();
}
You should have
#Override
public void deletePerson(final Person person, final DeleteListener deleteListener) {
final String id = person.getId();
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.where(Person.class).equalTo("mId", id).findAll().deleteAllFromRealm();
}
Here in you code you only query data asynchronously. For deletion use .remove() method while looping on result of query.
Suppose, that mId is #Primary key, removal will look like:
RealmResults<Person> results = realm.where(Person.class).equalTo("mId", person.getId()).findFirst().removeFromRealm();