1

I have two threads which don't work with UI thread. In one thread I receive JSON from server and save it to Realm DB :

Realm realm = Realm.getDefaultInstance();
final RealmResults<MyClass> all = realm.where(MyClass.class).findAll();
realm.executeTransaction(new Realm.Transaction() {
            @Override
           public void execute(Realm realm) {
           all.deleteAllFromRealm();
           realm.createOrUpdateAllFromJson(MyClass.class, recommendations);
      }
 });
 realm.close();

Then, in another thread after interaction with user I need to acquire this information, but it is unavailable :

 Realm realm = Realm.getDefaultInstance();
 RealmResults<MyClass> responseItems = realm.where(MyClass.class).findAll();
 realm.close();

So when I acquire data on the thread where I added them I can see them, on other threads they are unavailable. How can I merge information on different threads or notify instances to Update ?

Using : io.realm:realm-gradle-plugin:1.0.0

UPDATE : Information from different tables merges after application restart.

ilbets
  • 710
  • 1
  • 9
  • 35
  • It depends on if the other thread has a looper or not. If it is a looper thread, the update is triggered through handler event. You can use `Realm.addChangeListener()` to subscribe to the change event. For a thread without looper, you can use `Realm.waitForChange()` to know the data changes. See https://github.com/realm/realm-java/tree/master/examples/threadExample for more information. – beeender Jun 07 '16 at 02:16
  • I think you didn't understand my question correctly. For example, I started AsyncTask - added 5 elements to Realm than started new AsyncTask - try to acquire them but table is empty. – ilbets Jun 07 '16 at 11:12
  • If you open the Realm in ThreadA (data version1) before adding elements in ThreadB (data version2 after adding), Realm in ThreadA will stay at data version1 without seeing changes in version2 until next Looper event in Looper thread or `waitForChanges` return in non-looper thread. But if "added 5 elements to Realm then started new AsyncTask", it will be strange. Can you modify the question with some code showing the sequence of the two async tasks start? – beeender Jun 07 '16 at 11:24
  • call from the second async task is made much much later, so information is already in a table. – ilbets Jun 07 '16 at 11:41
  • If you can send us a sample project which can reproduce this issue, we are happy to take a look :) To help@realm.io if you want to share it privately. – beeender Jun 07 '16 at 11:49
  • Sorry but I cannot provide you my project, anyway, I think I find out what is wrong. I updated Realm instance first in the thread with Looper. Then I acquire data on the thread without looper. So I call realm.waitForChange(); and sometimes I get correct data, but if I do request data from DB a few time - realm return me new instance where I call waitForChange(); and it stuck - deadlock because there are already all up to date, I need to go back update anything and than it'll work. How to avoid this ? – ilbets Jun 07 '16 at 12:49
  • I found work around - even if I don't need any transaction I call .beginTransaction() befor call where(clazz.class) and and data is up to date. – ilbets Jun 07 '16 at 12:54
  • `.beginTransaction()` will move the realm version to the latest. Although it works in your side, I still think in your case you'd better use a looper thread with handler events to drive your logic. – beeender Jun 07 '16 at 12:57
  • Thanks, but for now my solution fit best for me. Maybe in future I'll try to update to looper thread. – ilbets Jun 08 '16 at 07:31
  • @beeender I am interested in how this looper thread could be implemented. Right now I am using `waitForChange` before every `where` operation, but I am not convinced this is the best solution as it could possibly cause deadlocks. I also tried the `RealmRefresh` method described here: http://stackoverflow.com/questions/38833163/realmchangelistener-does-not-get-called-when-realm-gets-updated-in-notificationl/38839808#38839808, but it is not working for me. – John Ernest Guadalupe Mar 07 '17 at 02:50
  • @JohnErnestGuadalupe actually any generic Android looper thread will do the trick. Check this answer http://stackoverflow.com/a/4855788/1396606 . – beeender Mar 08 '17 at 03:35

1 Answers1

3

I found a workaround - even if I don't need any transaction I call .beginTransaction() before call where(clazz.class) and data is up to date.

ilbets
  • 710
  • 1
  • 9
  • 35
  • Worked for me, I dont understand this. Also remember to commitTransaction after querying. – Dantalian Jun 10 '16 at 10:46
  • From the official documentation: _Before beginning a transaction, the Realm instance is updated to the latest version in order to include all changes from other threads._ – Nicola De Fiorenze Feb 06 '17 at 16:41