簡體   English   中英

如何在 Room Db 上使用掛起功能?

[英]How to use suspend function on Room Db?

我在 kotlin 中使用協程使用 Room Db。 這是我的道界面:

@Dao
interface CheckListNameDao {

    @Insert
    suspend fun insertName(name: CheckListName)


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

getAllNames()方法工作正常。 問題在於insertName()方法。 當我從insertName()方法中刪除suspend關鍵字時,它會引發此異常: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. 但是,當我使用suspend關鍵字時,我無法再構建項目。 它顯示以下錯誤:

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()

為什么顯示此錯誤? 我的代碼基於這個帶有視圖的 Android Room - Kotlin

編輯:這是我的存儲庫:

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)
        }
    }

這是視圖模型:

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))
        }
    }
}

編輯2:

添加suspend關鍵字時,我也收到此錯誤:

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);

這是CheckListName數據類:

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

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

        var name: String
)

根據Room Declaring Dependencies 文檔,您需要對room-ktx的依賴才能使用協程,並使用suspend方法:

implementation "androidx.room:room-ktx:2.2.3"

編輯:您的代碼是正確的,它可以用於具有掛起功能的房間數據庫。 只需像下面這樣編輯您的 Gradle 依賴項即可修復該錯誤。

如果您使用 kotlin 版本 ( 1.7.0 ) 應該使用房間最新的 alpha 版本 ( 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"

如果你想在穩定版本( 2.4.2 )中使用房間,應該使用 kotlin 版本( 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"

我都試過了,它們都有效。 這是參考:問題跟蹤器

以下代碼片段包含一個示例數據庫配置,其中包含一個實體和一個 DAO:

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val CheckListName: String?,
)

我在 kotlin 中使用協同程序使用 Room Db。 這是我的 Dao 界面:

@Dao
interface CheckListNameDao {

    @Insert
    suspend fun insertName(name: CheckListName)


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

getAllNames()方法工作正常。 問題出在insertName()方法上。 當我從insertName()方法中刪除suspend關鍵字時,它會拋出以下異常: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. 但是,當我使用suspend關鍵字時,我無法再構建項目。 它顯示以下錯誤:

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()

為什么會顯示這個錯誤? 我的代碼基於此Android Room with a View - Kotlin

編輯:這是我的存儲庫:

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)
        }
    }

這是視圖模型:

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))
        }
    }
}

編輯2:

添加suspend關鍵字時,我也收到此錯誤:

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);

這是CheckListName數據類:

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

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

        var name: String
)

暫停在 Room DAO 中不起作用,quires 返回 LiveData 並且 Kotlin 版本高於:1.4.32

更多請看這里: 鏈接

只改變你的樂趣:

@Insert(onConflict = OnConflictStrategy.REPLACE)

suspend fun insertName(name: CheckListName) : Long

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM