【问题标题】:Error with Room dao class when using Kotlin coroutines使用 Kotlin 协程时 Room dao 类出错
【发布时间】:2018-07-19 13:14:58
【问题描述】:

我正在尝试使用kotlin协程通过here描述的方法访问房间数据库,添加插件和依赖,并在gradle中启用kotlin协程。

gradle 文件中:

    kotlin {
    experimental {
        coroutines 'enable'
    }
}
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.21" ...}

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

道类

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

@Delete
suspend fun deleteEvent(event: MyEvent)
...

构建,然后得到这些错误

错误

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
...

我尝试删除生成的 dao 类并重建以重新生成它,但仍然出现这些错误。我考虑不使用lauch{} 方法而是使用suspend 关键字,因为代码中有很多地方可以查询db。

我该如何解决这个问题?

【问题讨论】:

    标签: android kotlin coroutine android-room


    【解决方案1】:

    在某些活动中,可能需要将 Room DB 代码行包装在 COROUTINE 中,如下面的代码所示。 (因为没有 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>
    

    在这种情况下,如果在 Dao 中没有使用 suspend 方法,这个活动就会崩溃。这意味着不可能摆脱协程或删除suspend方法。在这种情况下,如果你从 Dao 中移除 suspend 方法,并将 Activity 的协程更改为以下,它就可以正常工作。

    // at an Activity:    
    lifecycleScope.launch(Dispatchers.IO) {
          rcAdapter.helper = helper
          rcAdapter.listData.addAll(helper?.roomMemoDao()?.getAll() ?: listOf())
        }
    // at Dao:
    fun getAll(): List<Room>
    

    参见。 kotlin_version= '1.6.0' 和 room_version = "2.3.0"

    【讨论】:

      【解决方案2】:

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

      @Insert(onConflict = OnConflictStrategy.REPLACE)
      
      suspend fun insertCountry(country: Country) // here
      

      转换成这个解决了我的问题:

      @Insert(onConflict = OnConflictStrategy.REPLACE)
      
      fun insertCountry(country: Country)
      

      【讨论】:

        【解决方案3】:

        我通过将房间版本更改为最新的稳定版本(在撰写本文时为 2.3.0)来解决此问题,同时我当前的 Kotlin 版本是 1.5.10。

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

        【讨论】:

          【解决方案4】:

          其实是可以的,

          你需要使用:

          implementation "androidx.room:room-coroutines:${versions.room}"
          

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

          另外,对我有用的版本是:2.1.0-alpha04 所以,我的房间部门正是:

          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"
          

          【讨论】:

          • 我在 2.2.6 上,但它不工作。 2.3.0做到了
          【解决方案5】:

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

          Room 等待特定的方法签名生成代码。所以,在 Room 不直接支持协程之前,你不能对 DAO 使用挂起函数。

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

          1. 如果 DAO 方法返回值,使用 RxJava 或 LiveData 获取它并 使用 coroutine adapter for RxJava 或为 LiveData 编写自己的 (不知道现有的)
          2. 将同步 DAO 方法调用包装到 具有自己的线程池的协程(因为这样的调用会阻塞)。

          但如果可能的话,总是更喜欢选项 1,因为 Room 已经提供了非阻塞 API,只需使用协程适配器即可允许将此 API 与协程一起使用而无需回调

          Room 2.1.0-alpha03 开始,DAO 方法现在可以是suspend 函数。被特别注解为@Insert、@Update 或@Delete 的Dao 方法可以是挂起函数。注释为@Query 的插入、更新和删除是not yet supported,尽管普通查询是。更多详情请参阅:Architecture Components Release NotesFeature Request

          【讨论】:

          • 您是否对 Room 2.1.0-alpha3/4 的 viwmodel/repository 使用任何协程“模式”
          猜你喜欢
          • 1970-01-01
          • 2018-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-11
          • 2018-08-25
          • 1970-01-01
          相关资源
          最近更新 更多