We are starting to use Realm.io in an android app project. But something that we don't like with the Realm.io API is the absence of any asynchronous way to query the database. In old projects we used DbQuery and Sqlite, so we are used to make the database queries inside threads or AsyncTask
's. But is quite disturbing see that in all the examples the queries are made in the UiThread
. Isn't this a bad thing for the app performance?. We tried to make the queries inside threads or AsyncTasks but we get an error when we access our model objects back in the UiThread, saying that we cannot access RealObjects in threads that wasnt the ones where they was queried. Here is our example code:
service.getDatabaseHelper()
.with(getActivity()) //Context that I use to instance the Realm instance
.onFinishQuery( new DatabaseHelper.IQueryGetCallback<UserRealm>() {
@Override
public void onGetResult(UserRealm[] results) {
for(UserRealm aUser : results){
//Here is where it crashes
Log.d("Log","Username -> "+aUser.getName());
}
}
})
.getUsersFromDb();
//.......
//In our "DAO" class
public void getUsersFromDb(){
new GetQueryTask() {
@Override
public UserRealm[] onQueryReadyToBeExecuted(Realm realmInstance) {
RealmQuery<UserRealm> query = realmInstance.where(UserRealm.class);
RealmResults<UserRealm> result = query.findAll();
// TODO hacer que devuelva un array
ArrayList<UserRealm> users = new ArrayList<UserRealm>();
for (UserRealm u : result) {
//Here we can read the RealObject's fine
users.add(u);
}
return users.toArray(new UserRealm[users.size()]);
}
}.execute();
}
//Our abstract task that wraps all the instantiation-transaction behaviour
public abstract class GetQueryTask<T extends RealmObject> extends AsyncTask<Void, Void, T[]> {
@Override
protected T[] doInBackground(Void... params) {
//We tried to instantiate this class in several places, here
//Send it as parameter through the AsyncTask
//context is set in the with(Context ctx) method.
Realm realm = Realm.getInstance(context);
return onQueryReadyToBeExecuted(realm);
}
public abstract T[] onQueryReadyToBeExecuted(Realm realmInstance);
@Override
protected void onPostExecute(T[] result) {
mCallback.onExecute(result);
}
}
Our major concern isn't is the "bug" of this code, but if it's okay to do the queries in the UiThread as the Realm.io developers do in their examples. If is that the case, all this code to perform the queries asynchronously will not be neccesary any more.
No, it is not asynchronous.
Realm is an open source object database management system, initially for mobile operating systems (Android/iOS) but also available for platforms such as Xamarin, React Native, and others, including desktop applications (Windows), and is licensed under the Apache License.
In a current GlobalLogic project, we are managing a 3MB database in SQLite running on Android.
Realm is a database that is the perfect alternative to SQLite. It's is a NoSQL database designed for mobile platform. Its core consists of a self-contained C++ library. It supports Android and iOS both.
Christian from Realm here. You are right that queries are currently required to run on the thread they are used on, which potentially can have a negative effect on the UI thread performance. We are however acutely aware of this and are actively working on making it possible to move query results across threads.
That said queries in Realm are quite fast even for reasonable large amounts of data, and due to it only loading data you actually use can be very performant even when run on the UI thread.
I would encourage you to try it out with whatever data size you seem reasonable and test your performance (on a older device preferably :)). It is also possible to do tricks like adding indexes to keys, make the heavy query on a background thread, send keys to the UI thread and requery for them there. It is a bandaid but will work in some cases - Sadly not for lists though.
realm 0.84 support now async queries.
You can try it out by adding 'io.realm:realm-android:0.84.0-SNAPSHOT' to your build.gradle. There are a few new methods
You have to add a addChangeListener(RealmChangeListener) to the RealmResult to get notified when the query completes.
Documentation: https://realm.io/docs/java/latest/#asynchronous-queries
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With