Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Room with Kotlin-coroutines observe db changes

So, I recently started experimentation with coroutines, I switched from Rxjava2 to coroutines, I haven't got a grasp of it yet but still, I ran into a condition where I needed to observe my database change and update the UI corresponding to that.

RxJava used to provide me with Flowables, Completeable etc. using that I would be able to observe changes in Db.

    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): Flowable<List<SomeData>>

So here now I used to subscribe to getData and always used to observe changes

Now Enter coroutines, I am using a suspended function with a deferred result to return my responses

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    abstract fun insert(data: SomeData): Long

    @Query("SELECT * FROM somedata_table")
    abstract fun getData(): List<SomeData>
suspend fun getAllSomeData():Deferred<List<SomeData>>{
        return GlobalScope.async (context= coroutineContext){
            database.myDao().getData()
        }
    }

Now I have no way to listen for updates, Channels in coroutines might be the right answer? but I am not sure how to use it with Room.

like image 866
Rajat Beck Avatar asked Jan 31 '19 06:01

Rajat Beck


People also ask

Are coroutines lifecycle aware?

Kotlin coroutines provide an API that enables you to write asynchronous code. With Kotlin coroutines, you can define a CoroutineScope , which helps you to manage when your coroutines should run. Each asynchronous operation runs within a particular scope.

How do you use room coroutines?

This is the same executor that would be used by LiveData to do background work. Start using Room and coroutines in your app, the database work is guaranteed to be run on a non-UI Dispatcher. Mark your DAO method with the suspend modifier and call them from other suspend functions or coroutines!

Why coroutines are better than RxJava?

The reason is coroutines makes it easier to write async code and operators just feels more natural to use. As a bonus, Flow operators are all kotlin Extension Functions, which means either you, or libraries, can easily add operators and they will not feel weird to use (in RxJava observable.

What are Kotlin coroutines good for?

Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages. On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.


1 Answers

Use Room 2.2.0 Flows and kotlin coroutines. It's contentious but I dislike LiveData as it gives you results on the UI thread. If you have to do any data parsing you'll have to push everything back to another IO thread. It's also cleaner than using channels directly as you have to do extra openSubscription().consumeEach { .. } calls every time you want to listen to events.

Flow approach Requires the following versions:

// this version uses coroutines and flows in their non-experimental version

org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2
androidx.room:room-runtime:2.2.0
androidx.room:room-compiler:2.2.0

Dao:

@Dao
interface MyDao {
     @Query("SELECT * FROM somedata_table")
     fun getData(): Flow<List<SomeData>>
}

class to do observation:

launch {
   dao.getData().collect { data ->
    //handle data here
   }
}

if your calling class is not itself a CoroutineScope you'd have to call launch with the context of something that is. That can be GlobalScope or some other class you create. Here I'm using lifecycleScope assuming we're in an Activity class.

lifecycleScope.launch {
   dao.getData().collect { data ->
    //handle data here
   }
}

the collect lambda will receive every udpate to the table much like an Rx onNext call.

like image 98
Travis Castillo Avatar answered Sep 29 '22 13:09

Travis Castillo