使用Kotlin协程时,Room dao类出错

Rob*_*bin 7 android coroutine kotlin android-room

我正在尝试使用kotlin协同程序通过此处描述的方法访问room数据库,添加插件和依赖项,并在gradle中启用kotlin协同程序.

gradle文件中:

    kotlin {
    experimental {
        coroutines 'enable'
    }
}
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.21" ...}
Run Code Online (Sandbox Code Playgroud)

所以我suspend为dao类中的所有方法添加了关键字,如下所示:

道类

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

@Delete
suspend fun deleteEvent(event: MyEvent)
...
Run Code Online (Sandbox Code Playgroud)

并构建,然后得到这些错误

错误

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

错误链接导航到自动生成的 dao类.现在这个类中生成的方法每个都有一个这种类型的附加参数Continuation ,如下所示:

自动生成dao类

@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
...
Run Code Online (Sandbox Code Playgroud)

我尝试删除生成的dao类并重建以重新入侵它,仍然会得到这些错误.我认为不使用该lauch{}方法但使用suspend关键字,因为在代码中有很多地方可以查询db.

我怎样才能解决这个问题?

gil*_*dor 10

您不能使用suspendDAO方法.挂起在编译时处理的函数,编译器更改此函数的签名(不同的返回类型,状态机回调的附加参数),使其成为非阻塞函数.

房间等待特定方法签名生成代码.因此,直到Room不直接支持协同程序,您不能使用DAO的暂停功能.

目前,您有这样的解决方法:

  1. 如果DAO方法返回值,使用RxJava或LiveData获取它并使用corxine适配器用于RxJava为LiveData编写自己的(不知道现有的)
  2. 用自己的线程池包装同步DAO方法调用coroutine(因为这样的调用将被阻塞).

但是如果可能的话,总是更喜欢选项1,因为Room已经提供了非阻塞API,只需使用协程适配器允许在没有回调的情况下使用这个API和协同程序

从那时起Room 2.1.0-alpha03,DAO方法现在可以成为suspend函数.专门注释为@Insert,@ Update或@Delete的Dao方法可以是挂起函数.虽然普通查询是,但尚不支持注释为@Query的插入,更新和删除.有关详细信息,请参阅:体系结构组件发行说明功能要求.


小智 9

我通过将我的 Room 版本更改为最新的稳定版本(截至撰写本文时为 2.3.0)来修复此问题,同时我当前的 Kotlin 版本是 1.5.10。

一般来说,如果仍然有错误,我建议您对依赖项使用最新的稳定版本。


eri*_*tiz 6

其实是有可能的

你需要使用:

implementation "androidx.room:room-coroutines:${versions.room}"
Run Code Online (Sandbox Code Playgroud)

您可以按照本教程进行操作:https : //medium.com/androiddevelopers/room-coroutines-422b786dc4c5

此外,对我有用的版本是:2.1.0-alpha04 所以,我的 Room deps 是:

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"
Run Code Online (Sandbox Code Playgroud)


小智 6

我有同样的错误,后来我发现我在 DAO 类方法中使用了suspend关键字:

@Insert(onConflict = OnConflictStrategy.REPLACE)

suspend fun insertCountry(country: Country) // here
Run Code Online (Sandbox Code Playgroud)

转换为此解决我的问题:

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun insertCountry(country: Country)
Run Code Online (Sandbox Code Playgroud)