14

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?

Robin
  • 1,487
  • 4
  • 17
  • 29

10 Answers10

25

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.

Dirk
  • 3,030
  • 1
  • 34
  • 40
gildor
  • 1,789
  • 14
  • 19
12

actually it is possible,

you need to use:

implementation "androidx.room:room-coroutines:${versions.room}"

you can follow this tutorial: https://medium.com/androiddevelopers/room-coroutines-422b786dc4c5

Additionally, the version that worked for me was: 2.1.0-alpha04 So, my Room deps were exactly:

implementation "androidx.room:room-runtime:2.1.0-alpha04"
implementation "androidx.room:room-coroutines:2.1.0-alpha04"
kapt "androidx.room:room-compiler:2.1.0-alpha04"
erik.aortiz
  • 511
  • 5
  • 10
9

I fixed this by changing my room version to latest stable release (as at the time of writing, 2.3.0), meanwhile my current Kotlin version is 1.5.10.

Generally, I recommend you use the last stable release for your dependencies if you still have errors.

Tobi Denagan
  • 91
  • 1
  • 3
6

I have the same error and later I came to know that I used suspend keyword in my DAO class method:

@Insert(onConflict = OnConflictStrategy.REPLACE)

suspend fun insertCountry(country: Country) // here

Converted to this solve my issue :

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun insertCountry(country: Country)
Elikill58
  • 4,050
  • 24
  • 23
  • 45
Usama Zafar
  • 77
  • 1
  • 3
  • this actually looks like an answer not that hunt and peck versioning. There can be only one suspend and I would hope its farther upstream than the DAO interface. – danny117 Jan 05 '23 at 23:32
1

Changing the room version to it's latest stable version.

val room_version = "2.5.0" works for me.

My error was regarding Dao and Entity class.

RusArtM
  • 1,116
  • 3
  • 15
  • 22
0

In some activities, it may require to wrap the lines of Room DB code in a COROUTINE as shown in the code below. (because without COROUTINE it will crash.)

// at an Activity:
CoroutineScope(Dispatchers.Main).launch {
      rcAdapter.helper = helper
      rcAdapter.listData.addAll(helper?.roomDao()?.getAll() ?: listOf())
    }

// at Dao:
suspend fun getAll(): List<Room>

In that case, if the suspend method isn't used in Dao, this activity will crash. It means that it is impossible to get rid of the coroutine or remove the suspend method. In this case, if you remove the suspend method from Dao and change the activity's coroutine to the following, it works fine.

// at an Activity:    
lifecycleScope.launch(Dispatchers.IO) {
      rcAdapter.helper = helper
      rcAdapter.listData.addAll(helper?.roomMemoDao()?.getAll() ?: listOf())
    }
// at Dao:
fun getAll(): List<Room>

cf. kotlin_version= '1.6.0' and room_version = "2.3.0"

Young Lee
  • 1
  • 1
0

I solved this issue by upgrading room to latest stable version.

  • This doesn't answers the question. While you might have faced the same issue, the OP faced issue because of using `suspended` functions inside DAO. And the answer that solved the issue was [this](https://stackoverflow.com/questions/48694449/error-with-room-dao-class-when-using-kotlin-coroutines/73067335#73067335) . You can refer it – Abhishek Dutt Jul 23 '22 at 04:19
0

In my case i tried to Degrade the kotlin version

classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0' in the build.gradle

This worked for me

-1

Type of the parameter must be a class annotated with @Entity or a collection/array of it. kotlin.coroutines.Continuation<? super kotlin.Unit> continuation); ^

-1

In my case, I just upgrading room to latest stable version. [def room_version = "X.X.X"] I recommend you use the last stable stable version