简体   繁体   English

使用 Kotlin 协程时 Room dao class 出错

[英]Error with Room dao class when using Kotlin coroutines

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.我正在尝试使用 kotlin 协程通过此处描述的方法访问房间数据库,添加插件和依赖项,并在 gradle 中启用 kotlin 协程。

in gradle file:gradle文件中:

    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 中的所有方法添加了suspend关键字,如下所示:

dao class道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:错误链接导航到自动生成的 dao class。此 class 中生成的方法现在每个都有一个此类型Continuation的附加参数,如下所示:

auto generated dao class自动生成的 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.我尝试删除生成的 dao class 并重建以重新生成它,仍然出现这些错误。 I consider not using the lauch{} method but use suspend keyword, becuase there are many places in code to query db.我考虑不使用lauch{}方法,而是使用suspend关键字,因为代码中有很多地方可以查询数据库。

How can I fix this?我怎样才能解决这个问题?

You cannot use suspend methods for DAO.您不能对 DAO 使用suspend方法。 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. Room 等待特定的方法签名来生成代码。 So, until Room doesn't support coroutines directly, you cannot use suspend function for DAO.所以,除非 Room 不直接支持协程,否则您不能对 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)如果 DAO 方法返回值,则使用 RxJava 或 LiveData 获取它并为 RxJava使用协程适配器为 LiveData编写自己的(不知道现有的)
  2. Wrap synchronous DAO method call to coroutine with own thread pool (because such call will be blocking).用自己的线程池将同步 DAO 方法调用包装到协程(因为这样的调用会阻塞)。

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但如果可能的话,总是更喜欢选项 1,因为 Room 已经提供了非阻塞 API,只需使用协程适配器来允许将此 API 与没有回调的协程一起使用

As of Room 2.1.0-alpha03 , DAO methods can now be suspend functions.Room 2.1.0-alpha03 ,DAO 方法现在可以是suspend函数。 Dao methods specifically annotated as @Insert, @Update, or @Delete can be suspend functions.特别注释为@Insert、@Update 或@Delete 的 Dao 方法可以是挂起函数。 Inserts, Updates, and Deletes annotated as @Query are not yet supported although normal queries are.插入、更新和删除注释为 @Query尚不支持,尽管正常查询是。 For further details see: Architecture Components Release Notes and Feature Request .有关更多详细信息,请参阅:架构组件发行说明功能请求

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您可以按照本教程进行操作: https : //medium.com/androiddevelopers/room-coroutines-422b786dc4c5

Additionally, the version that worked for me was: 2.1.0-alpha04 So, my Room deps was exactly:此外,对我有用的版本是: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"

I have the same error and later I came to know that I used suspend keyword in my DAO class method我有同样的错误,后来我知道我在我的 DAO 类方法中使用了suspend关键字

@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)

suspend fun insertCountry(country: Country) <-- Here暂停乐趣 insertCountry(country: Country) <-- 这里

converted to this solve my error转换为这个解决我的错误

@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)

fun insertCountry(country: Country)有趣的插入国家(国家:国家)

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.我通过将我的房间版本更改为最新的稳定版本(在撰写本文时为 2.3.0)解决了这个问题,同时我当前的 Kotlin 版本是 1.5.10。

Generally, I recommend you use the last stable release for your dependencies if you still have errors.通常,如果您仍然有错误,我建议您使用最新的稳定版本作为您的依赖项。

In some activities, it may require to wrap the lines of Room DB code in a COROUTINE as shown in the code below.在某些活动中,可能需要将 Room DB 代码行包装在 COROUTINE 中,如下面的代码所示。 (because without COROUTINE it will crash.) (因为没有 COROUTINE 它会崩溃。)

// 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.在这种情况下,如果 Dao 中未使用 suspend 方法,则此活动将崩溃。 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.在这种情况下,如果您从 Dao 中删除 suspend 方法并将活动的协程更改为以下内容,则它可以正常工作。

// 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" kotlin_version = '1.6.0' 和 room_version = "2.3.0"

我通过将房间升级到最新的稳定版本解决了这个问题。

In my case i tried to Degrade the kotlin version就我而言,我尝试降级 kotlin 版本

classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0' in the build.gradle build.gradle 中的类路径 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0'

This worked for me这对我有用

In my case, I just upgrading room to latest stable version.就我而言,我只是将房间升级到最新的稳定版本。 def room_version = "2.4.3" //when I use "2.4.2" the problem is occurred. def room_version = "2.4.3" //当我使用 "2.4.2" 时出现问题。 I recommend you use the last stable stable version我建议你使用最后一个稳定的稳定版本

Changing the room version to it's latest stable version(val room_version = "2.5.0") Works for me.将房间版本更改为最新的稳定版本 (val room_version = "2.5.0") 对我有用。

My error was regarding Dao and Entity class.我的错误是关于道和实体 class。

Type of the parameter must be a class annotated with @Entity or a collection/array of it.参数的类型必须是使用 @Entity 注释的类或其集合/数组。 kotlin.coroutines.Continuation<? kotlin.coroutines.Continuation<? super kotlin.Unit> continuation); super kotlin.Unit> 延续); ^ ^

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM