Skip to content Skip to sidebar Skip to footer

Android -room Persistent Library - DAO Calls Are Async, Therefore How To Get Callback?

From what i have read Room doesn’t allow you to issue database queries on the main thread (as can cause delays on the main thread)). so imagine i am trying to update a textview

Solution 1:

If you want to do your query synchronously and not receive notifications of updates on the dataset, just don't wrap you return value in a LiveData object. Check out the sample code from Google.

Take a look at loadProductSync() here


Solution 2:

There is a way to turn off async and allow synchronous access.

when building the database you can use :allowMainThreadQueries()

and for in memory use: Room.inMemoryDatabaseBuilder()

Although its not recommended. So in the end i can use a in memory database and main thread access if i wanted super fast access. i guess it depends how big my data is and in this case is very small.

but if you did want to use a callback.... using rxJava here is one i made for a list of countries i wanted to store in a database:

public Observable<CountryModel> queryCountryInfoFor(final String isoCode) {
    return Observable.fromCallable(new Callable<CountryModel>() {
        @Override
        public CountryModel call() throws Exception {
            return db.countriesDao().getCountry(isoCode);
        }
    }).subscribeOn(Schedulers.io())
       
 .observeOn(AndroidSchedulers.mainThread());

}

you can then easily add a subscriber to this function to get the callback with Rxjava.


Solution 3:

As Bohsen suggested use livedata for query synchronously. But in some special case, we want to do some asynchronous operation based on logic. In below example case, I need to fetch some child comments for the parent comments. It is already available in DB, but need to fetch based on its parent_id in recyclerview adapter. To do this I used return concept of AsyncTask to get back the result. (Return in Kotlin)

Repositor Class

fun getChildDiscussions(parentId: Int): List<DiscussionEntity>? {
        return GetChildDiscussionAsyncTask(discussionDao).execute(parentId).get()
    }

private class GetChildDiscussionAsyncTask constructor(private val discussionDao: DiscussionDao?): AsyncTask<Int, Void, List<DiscussionEntity>?>() {
        override fun doInBackground(vararg params: Int?): List<DiscussionEntity>? {
            return discussionDao?.getChildDiscussionList(params[0]!!)
        }
    }

Dao Class

@Query("SELECT * FROM discussion_table WHERE parent_id = :parentId")
fun getChildDiscussionList(parentId: Int): List<DiscussionEntity>?

Solution 4:

Well, the right answer is to use ListenableFuture or Observable depending if you need one shot query or a new value emitted after database change and the framework you want to use.

From the doc "To prevent queries from blocking the UI, Room does not allow database access on the main thread. This restriction means that you must make your DAO queries asynchronous. The Room library includes integrations with several different frameworks to provide asynchronous query execution."

Exemple with a one shot query. You just have to add this in your gradle file.

// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"

Then your SQL query in your DAO become.

@Query("SELECT * FROM " + Event.TABLE_NAME)
ListenableFuture<List<Event>> getEventList();

Last step is the future call itself.

 ListenableFuture<List<Event>> future = dao.getEventList();
 future.addListener(new Runnable() {
    @Override
    public void run() {
        try {
            List<Event>> result = future.get();
        } catch (ExecutionException | InterruptedException e) {
        }
    }
}, Executors.newSingleThreadExecutor());

Source : https://developer.android.com/training/data-storage/room/async-queries#guava-livedata


Post a Comment for "Android -room Persistent Library - DAO Calls Are Async, Therefore How To Get Callback?"