Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with Room dao class when using Kotlin coroutines

I'm trying to use kotlin coroutines to access room database by the method described here, added the plugin and dependency, and enabled kotlin coroutines in gradle.

in gradle file:

    kotlin {
    experimental {
        coroutines 'enable'
    }
}
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.21" ...}

So I added suspend keyword for all the methods in dao class, like this:

dao class

@Query("select * from myevent")
suspend fun all(): List<MyEvent>

@Delete
suspend fun deleteEvent(event: MyEvent)
...

and build, then get these errors

error

e: C:\Users\projectpath\app\build\tmp\kapt3\stubs\debug\com\robyn\myapp\data\source\local\EventsDao.java:39: error: Deletion methods must either return void or return int (the number of deleted rows). public abstract java.lang.Object deleteEventById(@org.jetbrains.annotations.NotNull() ^ e: C:\Users\projectpath\app\build\tmp\kapt3\stubs\debug\com\robyn\myapp\data\source\local\EventsDao.java:41: error: Query method parameters should either be a type that can be converted into a database column or a List / Array that contains such type. You can consider adding a Type Adapter for this. kotlin.coroutines.experimental.Continuation<? super kotlin.Unit> p1);

the error links navigate to the auto generated dao class. The generated methods in this class now each has an additional param of this type Continuation , as this:

auto generated dao class

@org.jetbrains.annotations.Nullable()
@android.arch.persistence.room.Delete()
public abstract java.lang.Object deleteAllEvents(@org.jetbrains.annotations.NotNull() // error indicates at this line
java.util.List<com.robyn.myapp.data.MyEvent> events, @org.jetbrains.annotations.NotNull()
kotlin.coroutines.experimental.Continuation<? super kotlin.Unit> p1); // error indicates at this line
...

I tried delete the generated dao class and rebuild to renegerate it, still get these errors. I consider not using the lauch{} method but use suspend keyword, becuase there are many places in code to query db.

How can I fix this?

like image 874
Robin Avatar asked Feb 08 '18 20:02

Robin


People also ask

Does room support database transactions using Kotlin coroutines?

With the release of Version 2.1, the library added support for database transactions using coroutines. Implement suspension functions on Data Access Objects (or DAO) in Room. Call them using Kotlin’s coroutines for database transactions.

Why can’t I suspend a DAO in Kotlin?

This is because the DAO methods are missing something very important: suspend keyword. In Kotlin, a suspension function is a function that can suspend the execution of a coroutine. This means the coroutine can pause, resume or cancel.

How to implement a dao with room and coroutines?

If you’re interested to check out the implementation, check out the CoroutinesRoom.java and RoomDatabase.kt 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!

What are coroutines in room persistence library?

In this tutorial, you’ll learn how to use coroutines with the Room persistence library to allow for asynchronous database operations. Room is Google’s architecture components library for working with SQLite on Android. With the release of Version 2.1, the library added support for database transactions using coroutines.


1 Answers

You cannot use suspend methods for DAO. Suspend function processed in compile time and compiler changes the signature of this function (different return type, an additional argument for state machine callback) to make it non-blocking.

Room waits for particular method signature to generate code. So, until Room doesn't support coroutines directly, you cannot use suspend function for DAO.

For now, you have such workarounds:

  1. If DAO method returns value, use RxJava or LiveData to get it and use coroutine adapter for RxJava or write your own for LiveData (don't know existing ones)
  2. Wrap synchronous DAO method call to coroutine with own thread pool (because such call will be blocking).

But always prefer option 1 if it's possible because Room already provides non-blocking API, just use coroutine adapter to allow use this API with coroutines without callbacks

As of Room 2.1.0-alpha03, DAO methods can now be suspend functions. Dao methods specifically annotated as @Insert, @Update, or @Delete can be suspend functions. Inserts, Updates, and Deletes annotated as @Query are not yet supported although normal queries are. For further details see: Architecture Components Release Notes and Feature Request.

like image 167
gildor Avatar answered Oct 09 '22 07:10

gildor