Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use suspend function on Room Db?

I am using Room Db using coroutines in kotlin. This is my Dao interface:

@Dao
interface CheckListNameDao {

    @Insert
    suspend fun insertName(name: CheckListName)


    @Query("SELECT * FROM CheckListNamesTable")
    fun getAllNames(): LiveData<List<CheckListName>>
}

getAllNames() method works fine. The problem is with the insertName() method. When I remove the suspend keyword from the insertName() method, it throws this exception: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. But, when I use suspend keyword, I cannot build the project anymore. It shows the following error:

error: Methods annotated with @Insert can return either void, long, Long, long[], Long[] or List<Long>.
public abstract java.lang.Object insertName(@org.jetbrains.annotations.NotNull()

Why this error is showing? My code is based on this Android Room with a View - Kotlin

Edit: This is my repository:

class MainRepository(application: Application) {

        private var nameDao: CheckListNameDao = AppDatabase.getDatabase(application.applicationContext)
                .checkListNameDao()

        fun getAllNames(): LiveData<List<CheckListName>> {
            return nameDao.getAllNames()
        }

        suspend fun setNewListName(checkListName: CheckListName) {
            nameDao.insertName(checkListName)
        }
    }

This is the viewmodel:

class MainViewModel(application: Application) : AndroidViewModel(application) {

    private var mainRepository = MainRepository(application)

    fun getAllNames(): LiveData<List<CheckListName>> {
        return mainRepository.getAllNames()
    }

    fun setNewListName(name: String) {
        viewModelScope.launch {
            mainRepository.setNewListName(CheckListName(0, name))
        }
    }
}

EDIT 2:

I am also getting this error when I add the suspend keyword:

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

This is the CheckListName data class:

@Entity(tableName = "CheckListNamesTable")
data class CheckListName(

        @PrimaryKey(autoGenerate = true)
        var id: Int,

        var name: String
)
like image 390
Jayesh Babu Avatar asked Feb 04 '20 05:02

Jayesh Babu


People also ask

How does suspend function work?

A suspending function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking. The syntax of a suspending function is similar to that of a regular function except for the addition of the suspend keyword.

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!

What is suspend keyword in Kotlin?

If you notice the functions closely, they can be used to resume the coroutine with a return value or with an exception if an error had occurred while the function was suspended. This way, a function could be started, paused, and resume with the help of Continuation. We just have to use the suspend keyword.

How do I clear a room DB?

3.1 Add the Clear all data menu option In the Options menu, select Clear all data. All words should disappear. Restart the app. (Restart it from your device or the emulator; don't run it again from Android Studio) You should see the initial set of words.


2 Answers

As per the Room Declaring Dependencies documentation, you need a dependency on room-ktx to use Coroutines and, with that, suspend methods:

implementation "androidx.room:room-ktx:2.2.3"
like image 197
ianhanniballake Avatar answered Oct 15 '22 01:10

ianhanniballake


If you using kotlin version (1.7.0) shoud work with room latest alpha version (2.5.0-alpha02)

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0"

implementation "androidx.room:room-runtime:2.5.0-alpha02"
implementation "androidx.room:room-ktx:2.5.0-alpha02"
kapt "androidx.room:room-compiler:2.5.0-alpha02"

If you want using room in stable version (2.4.2) should work with kotlin version (1.6.20)

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20"

implementation "androidx.room:room-runtime:2.4.2"
implementation "androidx.room:room-ktx:2.4.2"
kapt "androidx.room:room-compiler:2.4.2"

I have tried both and they work. this is the reference: issue tracker

like image 37
khanif piper Avatar answered Oct 15 '22 01:10

khanif piper