CrimeDao can't be built witih suspend functions

Using the eBook, PDF, I’m following all the instructions in chapter 12: “Coroutines and Databases”. I’ve gotten all the way through defining the CriminalIntentApplication object and adding it to the manifest. But what I go to build…

With CrimeDao defined as this:

package com.selbie.criminalintent.CrimeDatabase
import androidx.room.Dao
import androidx.room.Query
import com.selbie.criminalintent.Crime
import java.util.*

@Dao
interface CrimeDao {
    @Query("SELECT * from crime")
    suspend fun getCrimes() : List<Crime>

    @Query("SELECT * FROM crime WHERE id=(:id)")
    suspend fun getCrime(id: UUID):Crime
}

I get a lot of errors as shown below. I found a Stack Overflow article saying Dao’s can’t contain suspend functions. So I removed suspend keyword from each and it builds fine. Is there something I missed? I’m specifying id 'org.jetbrains.kotlin.kapt' version '1.6.10' apply false in the build.gradle as well as version 2.4.2 for the three Room dependencies the eBook instructed me to add.

Is there a fix such that Dao functions can have suspend functions? If I remove suspend from these function declarations, will that block me later?

C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:11: error: Not sure how to convert a Cursor to this method's return type (java.lang.Object).
    public abstract java.lang.Object getCrimes(@org.jetbrains.annotations.NotNull()
                                     ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:12: 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.Continuation<? super java.util.List<com.selbie.criminalintent.Crime>> continuation);
                                                                                            ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:11: error: Unused parameter: continuation
    public abstract java.lang.Object getCrimes(@org.jetbrains.annotations.NotNull()
                                     ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:16: error: Not sure how to convert a Cursor to this method's return type (java.lang.Object).
    public abstract java.lang.Object getCrime(@org.jetbrains.annotations.NotNull()
                                     ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:18: 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.Continuation<? super com.selbie.criminalintent.Crime> continuation);
                                                                            ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:16: error: Unused parameter: continuation
    public abstract java.lang.Object getCrime(@org.jetbrains.annotations.NotNull()
                                     ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:11: warning: The query returns some columns [id, title, date, isSolved, requiredPolice] which are not used by java.lang.Object. You can use @ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with @RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns.  You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: id, title, date, isSolved, requiredPolice.
    public abstract java.lang.Object getCrimes(@org.jetbrains.annotations.NotNull()
                                     ^
C:\Users\jselbie\source\repos\AndroidStudioProjects\CriminalIntent\app\build\tmp\kapt3\stubs\debug\com\selbie\criminalintent\CrimeDatabase\CrimeDao.java:16: warning: The query returns some columns [id, title, date, isSolved, requiredPolice] which are not used by java.lang.Object. You can use @ColumnInfo annotation on the fields to specify the mapping. You can annotate the method with @RewriteQueriesToDropUnusedColumns to direct Room to rewrite your query to avoid fetching unused columns.  You can suppress this warning by annotating the method with @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH). Columns returned by the query: id, title, date, isSolved, requiredPolice.
    public abstract java.lang.Object getCrime(@org.jetbrains.annotations.NotNull()

Can you share the list of dependencies in the app/build.gradle file? I want to make sure you have the coroutines library in there.

To solve this problem, you can use the room-ktx library, which provides support for suspend functions. To do this, you need to make the following changes:
In the build.gradle file, add a dependency on room-ktx:
implementation “androidx.room:room-ktx:2.4.2”
Change the declaration of functions in the CrimeDao interface to use Flow instead of suspend:
@Query(“SELECT * from crime”)
fun getCrimes(): Flow<List>

@Query(“SELECT * FROM crime WHERE id=(:id)”)
fun getCrime(id: UUID): Flow.
Notice that the return types are now changed to Flow<List> and Flow, respectively.

After making these changes, Room will convert query results correctly and notify you of any data changes.

Good luck with developing your application!

1 Like

Hi @jselbie
I am having the same issue. If you solved it, can you please share how you solved the issue?

I think the mismatch is happening because crime-database have only [id, title, date, isSolved] as columns and data file has [id, title, date, isSolved, requiredPolice].

Can anyone confirm and help with this issue

There have been a lot of issues over the past year or so getting Room working in your standard Android project. A lot of different tools work together in order to make everything work. In order to get everything to work together, I recommend using the latest Android SDK versions in your project (covered in Chapter 8), using the latest versions of the Android Gradle plugin and the Kotlin Gradle plugin, using Java 17 for compiling your app (Java versions in Android builds  |  Android Studio  |  Android Developers), and using the latest version of the Room library.

1 Like

A bit late in my reply, but I found a workaround and published it as a post here: Fix for Chapter 12 build errors: "Not sure how to convert a Cursor" build error

thank you for share with us.