Android – what is the right way to handle multithreading and realm?
On my Android application, I have a data access layer. I have the following properties on each data storage class
Realm realm = Realm.getDefaultInstance();
My problem is when I try to call any data storage method from different threads. Then I understand
I've read that I should create a new realm instance on a new thread. The problem is that the data access layer is not thread aware. It doesn't know whether it is called from main or separated. In my opinion, it will smell adding logic to check
I checked different questions here and filled in the questions on GitHub, but I don't know the correct way to deal with this situation. I don't think I'm dealing with a strange scene
edit
My architecture is fragment, which contains a presenter with datastore
I detected a very long running process, so I moved it to such a separate thread in the presenter
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// Events is a collection of DTOs, they are not Realm objects (converted from Realm object to DTO inside dataStore)
events = dataStore.getEvents(filterTerm);
view.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (events.size() > 0) {
view.showEvents(events);
}
}
});
}
});
thread.start();
edit
Add 3 consecutive queries. They come from 3 different methods
Query 1
final RealmResults<Event> results = query.findAllAsync();
results.addchangelistener(new Realmchangelistener() {
@Override
public void onChange() {
....
}
});
Query 2
final RealmResults<T> result = realm.where(type).findAllAsync();
result.addchangelistener(new Realmchangelistener() {
@Override
public void onChange() {
...
}
});
Query 3
final RealmResults<PresentationSpeaker> results = query.findAllAsync();
results.addchangelistener(new Realmchangelistener() {
@Override
public void onChange() {
...
}
});
resolvent:
In general, custom makes your datastore asynchronous to avoid the problems you encounter now: the operation takes a long time, and you must create a custom thread and use postrunnable. This should be the focus of datastore, not the presenter and UI that should run on the UI thread. One solution is to make your data store asynchronous, Or you can implement some observer patterns yourself or use rxjava. Then, you can use the realms asynchronous API( https://realm.io/docs/java/latest/#asynchronous -Queries) do the following:
// DataStore
public class DataStore {
private final Realm realm;
public DataStore() {
realm = Realm.getDefaultInstance(); // Called on the UI thread
}
public void getEvents(EventsLoadedListener listener) {
RealmResults<Event> results = realm.where(Events.class).findAllAsync();
results.addchangelistener(new Realmchangelistener() {
public void onChange() {
if (listener != null) {
listener.eventsLoaded(results);
}
}
});
}
public interface EventsLoadedListener {
public void eventsLoaded(List<Event> events);
}
}
// UI code
datastore.getEvents(new DataStore.EventsLoadedListener() {
public void eventsLoaded(List<Event> events) {
view.showEvents(events);
}
})
Using rxjava can greatly simplify the above code, so I really encourage you to study it. Real restore students support rxjava: https://realm.io/docs/java/latest/#rxjava