Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve the following in Realm for android

In my applications, I usually have a loader that loads the data from sqlite and then passes it on to either the activity or fragment it is attached, from where it is set in the adapter of a absListView which then presents it to the user

Since realm states that its objects shouldn't be shared across threads, how can this be achieved without making any db calls from the UI thread? (which would make the app feel sluggish as I hit the db a good amount)

Also in the 3 examples - intro, gridView & migration, a number of times db operations are done in the UI thread. Isn't database operations in UI thread heavily frowned in Android?

Quoted from the docs - Potentially long running operations such as network or database operations, or computationally expensive calculations such as resizing bitmaps should be done in a worker thread (or in the case of databases operations, via an asynchronous request).

like image 233
x-treme Avatar asked Oct 28 '14 06:10

x-treme


2 Answers

You are right, currently it is not possible to load items on a background thread and then parse it to the UI thread. It is on the roadmap however, see here: https://github.com/realm/realm-java/issues/503

Realm is pretty fast though, so until then, for smaller amounts of data you would probably not skip frames even though you load data on the UI thread.

like image 66
Christian Melchior Avatar answered Oct 28 '22 16:10

Christian Melchior


When first time I read about realm on their site, I was very excited by looking their benchmark test. However, when I came down to the limitation part, I stuck there for 2 minutes and was thinking about "object share prevention across threads". From inside, it was telling me that go for realm but that limitation holding me back. So finally I decided to implement some kind of wrapper that allows me to share that object across all threads.

Here is the thing. Process of reading and writing to disk takes more time then simple object creation. This is the point that I carry with wrapper creation.

1) I keep allows to create object of subclass of realmObject anywhere against their rule of object access on same thread on which it is created.

e.g.

XyzsubclassofRealmObject xyzObject = new XyzsubclassofRealmObject();

2) Pass this object to the method that performs database operation

e.g.

insertOrUpdate(xyzObject);

//implementation
insertOrUpdate(XyzsubclassofRealmObject object) //you can make this method generic to accept any object that is subclass of RealmObject
{
    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    XyzsubclassofRealmObject databaseObject = realm.copyToRealmOrUpdate(object);
    //notice this copyToRealmOrUpdate method provides by Realm
    realm.commitTransaction();
    XyzsubclassofRealmObject copyObject = clone(databaseObject);        
    return copyObject;
}

3) Now there are also two point they mentioned that

  • subclass of RealmObject only have default getter and setter method and allows static method if wants our other logic. thank god they allows static method. :)

  • it can implement interface with no methods. :(

I was thinking of cloning the databaseObject that returned from copyToRealmOrUpdate. As interface with no method allows (i.e. 2nd point), 1st point came to help me.

public static XyzsubclassofRealmObject clone(XyzsubclassRealmObject databaseObject)
{
      XyzsubclassOfRealmObject obj = new XyzsubclassofRealmObject();
      obj.setXyz(databaseObject.getXyz());
      return obj;
}

Instead of calling directly clone method as shown here, I used reflection method to call clone method as I wrote generic wrapper to perform database operation instead of for specific model. You are free to choose your own way

That's it. You are done. As you see, we are returning copied object instead of database object, you are free to use it on any thread. :)

Conclusion: Many blogs and posts tells it is so faster in performance it is fine to use it on UI thread while performing transactions. But choice depends on you. You don't know in advance that how much data going to in or out from database by the time when your application usage is increasing. If that transaction will have enough data to make your UI sluggish, it will. Also we all developers have practice to perform database and network operation on worker thread instead of UI thread so it will not stop any UI interaction.

Process of reading and writing to disk takes more time then simple object creation

like image 35
Ripal Tamboli Avatar answered Oct 28 '22 16:10

Ripal Tamboli