Skip to content

Android Room Persistence Library : Pro tips and tricks

Android Room is an abstraction layer on top of SQLite that makes it easier and efficient to persist data. If you’re a new guy for trying the library, please read below tips and tricks for making your weekends happier!

Never use allowMainThreadQueries() 

You might be referring to many blogs and medium posts for implementing Room other than official Android documentation. One thing I found in them was the use of allowMainThreadQueries() method! You should never ever use this method for building your database class. You have to use another thread for all database queries (Especially for queries with insert/update/delete).

Never use AsyncTask.class for your queries

When I have proposed the ban on allowMainThreadQueries(), You may be thinking of implementing an AsycTask class for your database queries. Sometimes AsyncTask also fails to make your DB queries. Once you go through the AsyncTask documentation you can find something like this

AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the packagejava.util.concurrent such as,ExecutorThreadPoolExecutor and.FutureTask

So you must move your queries to any services or any other thread maintainers. A simple example using Executor.class is given below.

Executor myExecutor = Executors.newSingleThreadExecutor();
myExecutor.execute(() -> {
    myDao.insert(userObject);
});

Use synchronized for accessing database

Usually, you only need one instance of the Room database for the whole app. In order to maintain this implementation, You have to create a singleton instance which gives the database instance using the synchronized method. So that, You can ensure the concurrent access of database is synchronized along the whole thread.

//Sample database instance class.
static UserDatabase INSTANCE;

public static UserDatabase getDatabase(final Context context) {
    if (INSTANCE == null) {
        synchronized (UserDatabase.class) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                        UserDatabase.class, "database_name")
                        .build();

            }
        }
    }

    return INSTANCE;
}

Bundle your queries together in DAO interface

If your query abstract function uses another two queries function, You can wrap them together in your DAO class. So that you can avoid boilerplate codes.

@Dao
abstract class UserDao {
    
    //Bundles to calls together here.
    @Transaction
    open fun updateData(users: List<User>) {
        deleteAllUsers()
        insertAll(users)
    }
    @Insert
    abstract fun insertAll(users: List<User>)
    @Query("DELETE FROM Users")
    abstract fun deleteAllUsers()
}
Published inAndroidFirebaseKotlin

4 Comments

  1. So helpful, thank you so much

  2. Jeswin Jose Jeswin Jose

    Very nice.

  3. Zun Zun

    Thanks for this post. There’s one thing I still do not understand: why not use AsyncTask?

    Take this part of your post:
    `AsyncTasks should ideally be used for short operations (a few seconds at the most.)`

    Under what situation will my query take longer than a second to run? It only takes a few milliseconds. I also can not imagine a query taking longer than a second to execute.

    Could you also tell me more about `Sometimes AsyncTask also fails to make your DB queries`, or link me to another post which further explains this as I can’t find anything about it.

Leave a Reply

Your email address will not be published. Required fields are marked *