Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm.io and asynchronous queries

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.

like image 307
4gus71n Avatar asked Jan 06 '15 19:01

4gus71n


People also ask

Is Realm asynchronous?

No, it is not asynchronous.

Is Realm an online database?

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.

What database does Realm use?

In a current GlobalLogic project, we are managing a 3MB database in SQLite running on Android.

What is Realm NoSQL database in 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.


2 Answers

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.

like image 200
Christian Melchior Avatar answered Oct 14 '22 06:10

Christian Melchior


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

  • findAllAsync
  • findAllSortedAsync
  • findFirstAsync

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

like image 41
Fabian Avatar answered Oct 14 '22 06:10

Fabian