Room报错:无法将Cursor转换为方法返回类型
问题描述
我是Android开发新手,目前正在开发名为water drink reminder的项目,以下是我编写的Dao与数据库相关代码。每次运行应用时都会抛出错误 "Room Not sure how to convert a Cursor to this method's return type"。我检索相关问题后了解到**"不要将LiveData与suspend关键字搭配使用"**,但检查代码后我并未这样使用,却仍然出现该报错,恳请大家帮忙排查解决。
相关代码
Dao层
@Dao interface Dao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUser(user :User) @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertDrinkData(drink: Drink) @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertNotificationInfo(notification : Notification) @Update(onConflict = OnConflictStrategy.REPLACE) suspend fun updateUser(user: User) @Update(onConflict = OnConflictStrategy.REPLACE) suspend fun updateNotificationInfo(notification: Notification) @Delete suspend fun deleteSelectedDrinkData(drink : Drink) @Query("SELECT *FROM User_table") fun getAllUsers() : LiveData<List<User>> @Query("SELECT * FROM $USER_TABLE_NAME LIMIT 1") suspend fun readUserData() : User @Query("SELECT * FROM $USER_TABLE_NAME LIMIT 1") fun readData() : LiveData<User> @Query("SELECT * FROM $USER_TABLE_NAME LIMIT 1") suspend fun readNotificationData() : Notification @Query("SELECT $COLUMN_DATE_DRINK , SUM($COLUMN_AMOUNT_DRINK) as Total GROUP BY $COLUMN_DATE_DRINK") suspend fun readDrinkSumData() : MutableList<Sum> @Query("SELECT $COLUMN_DATE_DRINK , SUM($COLUMN_AMOUNT_DRINK) as Total GROUP BY $COLUMN_DATE_DRINK") fun readDrinkData() : LiveData<MutableList<Sum>> @Query("SELECT * FROM $USER_TABLE_NAME WHERE $COLUMN_DATE_DRINK = :date") suspend fun readDrinkDataSelectedDay(date:String): MutableList<Drink> }
数据库定义
@Database(entities = [User::class,Drink::class,Notification::class], version = DATABASE_VERSION) abstract class AppDataBase : RoomDatabase() { abstract val daoInstance : Dao companion object { private var INSTANCE : AppDataBase? = null fun getInstance(context : Context) : AppDataBase { synchronized(this) { var instance : AppDataBase? = INSTANCE if (instance == null) { instance = Room.databaseBuilder( context.applicationContext, AppDataBase::class.java, "AppDataBase" ).build() } return instance } } } }
Repository层
class AppRepository(private val dao: Dao) { fun readData() : LiveData<User> = dao.readData() fun readDrinkData(): LiveData<MutableList<Sum>> = dao.readDrinkData() suspend fun insertUser(user :User): Unit = dao.insertUser(user) suspend fun insertDrinkData(drink: Drink): Unit = dao.insertDrinkData(drink) suspend fun insertNotificationInfo(notification : Notification): Unit = dao.insertNotificationInfo(notification) suspend fun updateUser(user: User) : Unit = dao.updateUser(user) suspend fun updateNotificationInfo(notification: Notification): Unit = dao.updateNotificationInfo(notification) suspend fun readUserData() : User = dao.readUserData() suspend fun readNotificationData() : Notification = dao.readNotificationData() suspend fun deleteSelectedDrinkData(drink : Drink): Unit = dao.deleteSelectedDrinkData(drink) suspend fun readDrinkSumData(): MutableList<Sum>? = dao.readDrinkSumData() suspend fun readDrinkDataSelectedDay(date: String): MutableList<Drink>? { return dao.readDrinkDataSelectedDay(date) } }
环境信息
- 当前使用Room版本:2.4.2
- 错误截图:

问题原因与修复方案
报错核心原因是Room不支持将MutableList作为查询方法的返回类型,无论你是用suspend函数直接返回,还是包裹在LiveData中返回,Room默认只支持自动映射为不可变的List<T>类型,你代码中三处使用MutableList作为查询返回值,直接触发了Cursor无法转换的错误。
另外代码里还有两个隐藏问题会导致后续运行报错:
- SQL语句
SELECT *FROM User_table中*和FROM之间缺少空格,存在语法风险 readNotificationData()方法查询的是用户表$USER_TABLE_NAME,但返回类型是Notification实体,表和返回类不匹配
具体修复步骤
- 修改Dao层所有返回
MutableList的方法,将返回类型替换为List:// 替换对应三个查询方法 @Query("SELECT $COLUMN_DATE_DRINK , SUM($COLUMN_AMOUNT_DRINK) as Total GROUP BY $COLUMN_DATE_DRINK") suspend fun readDrinkSumData() : List<Sum> @Query("SELECT $COLUMN_DATE_DRINK , SUM($COLUMN_AMOUNT_DRINK) as Total GROUP BY $COLUMN_DATE_DRINK") fun readDrinkData() : LiveData<List<Sum>> @Query("SELECT * FROM $USER_TABLE_NAME WHERE $COLUMN_DATE_DRINK = :date") suspend fun readDrinkDataSelectedDay(date:String): List<Drink> - 修正SQL语法问题,将
SELECT *FROM User_table改为SELECT * FROM User_table - 修正
readNotificationData()的查询表名,替换为Notification实体对应的表名常量 - 同步修改Repository层对应方法的返回类型,去掉多余的可空声明,和Dao层返回类型保持一致:
fun readDrinkData(): LiveData<List<Sum>> = dao.readDrinkData() suspend fun readDrinkSumData(): List<Sum> = dao.readDrinkSumData() suspend fun readDrinkDataSelectedDay(date: String): List<Drink> { return dao.readDrinkDataSelectedDay(date) } - 额外检查:自定义统计结果类
Sum要保证字段名和查询返回的列名完全匹配,比如查询中聚合结果别名为Total,Sum类中对应字段要么命名为total/Total,要么用@ColumnInfo(name = "Total")注解标注,避免字段映射失败。
修改完成后Clean工程重新编译,该Cursor转换报错就会消失。
内容的提问来源于stack exchange,提问作者Pegah Jadidi
相关产品推荐
相关产品推荐

