代码之家  ›  专栏  ›  技术社区  ›  Robin

使用Kotlin协同例程时房间dao类出错

  •  10
  • Robin  · 技术社区  · 7 年前

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

    在里面 格拉德尔 文件:

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

    所以我补充道 suspend dao类中所有方法的关键字,如下所示:

    dao类

    @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{} 方法,但使用 关键字,因为代码中有很多地方可以查询数据库。

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

    6 回复  |  直到 7 年前
        1
  •  20
  •   Dirk richarbernal    6 年前

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

    Room等待特定的方法签名来生成代码。所以,除非Room不直接支持协同路由,否则不能对DAO使用挂起函数。

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

    1. 若DAO方法返回值,则使用RxJava或LiveData获取该值,并 使用 coroutine adapter for RxJava 或者为LiveData编写自己的 (不知道现有的)
    2. 将同步DAO方法调用包装到 与自己的线程池协同路由(因为这样的调用将被阻塞)。

    但如果可能的话,请始终选择选项1,因为Room已经提供了非阻塞API,只需使用协同路由适配器,就可以将此API与无回调的协同路由一起使用

    截至年月日 Room 2.1.0-alpha03 ,DAO方法现在可以 功能。专门注释为@Insert、@Update或@Delete的Dao方法可以是挂起函数。注释为@Query的插入、更新和删除是 not yet supported 虽然普通查询是。有关更多详细信息,请参阅: Architecture Components Release Notes Feature Request .

        2
  •  9
  •   eriknyk    3 年前

    实际上这是可能的,

    您需要使用:

    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"
    
        3
  •  8
  •   Tobi Denagan    3 年前

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

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

        4
  •  3
  •   Elikill58    3 年前

    我也有同样的错误,后来我才知道 我的DAO类方法中的关键字:

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

    转换为解决我的问题:

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    
    fun insertCountry(country: Country)
    
        5
  •  0
  •   Young Lee    3 年前

    在某些活动中,可能需要将房间DB代码行包装在一个协同例程中,如下面的代码所示。(因为如果没有协同程序,它将崩溃。)

    // 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方法,则此活动将崩溃。这意味着不可能摆脱协同程序或删除挂起方法。在这种情况下,如果从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\u版本=“1.6.0”和room\u版本=“2.3.0”

        6
  •  0
  •   Muhsinjon Mirgulshanov    2 年前

    参数的类型必须是用@Entity或其集合/数组注释的类。 科特林。协同程序。继续(<);?超级科特林。单位(>);续); ^