Room DAO报错:无法将Cursor转换为方法返回类型DataState该如何解决?
问题解决方案
错误根本原因
Room 原生不支持将查询返回的 Cursor 直接转换为你自定义的DataState密封类,仅支持以下几类返回类型:
- 实体类/实体类集合
Flow<T>、LiveData<T>、RxJava 相关的响应式类型- 加
suspend修饰时返回实体类/实体类集合
你直接在DAO层返回封装后的DataState类型,Room 无法识别转换逻辑,所以抛出该错误。
具体修改步骤
1. 修改DAO层代码
将返回类型改为Room支持的List类型,增加suspend修饰适配协程调用:
@Query("SELECT * FROM notification_list ORDER BY id ASC") abstract suspend fun readAllData(): List<NotificationItemsResponse.NotificationItemData>
如果需要监听数据库变化自动刷新,可直接返回Flow类型:
@Query("SELECT * FROM notification_list ORDER BY id ASC") abstract fun readAllDataFlow(): Flow<List<NotificationItemsResponse.NotificationItemData>>
2. 修改UseCase层代码
在UseCase层对DAO返回的结果手动封装DataState即可:
class GetNotificationListItemDetailsUseCase @Inject constructor(private val notificationDao: NotificationDao): BaseFlowUseCase<Unit, DataState<List<NotificationItemsResponse.NotificationItemData>>>() { override fun create(params: Unit): Flow<DataState<List<NotificationItemsResponse.NotificationItemData>>> { return flow{ emit(DataState.Loading) try { emit(DataState.Success(notificationDao.readAllData())) } catch(e: Exception) { emit(DataState.Error(e)) } } } }
如果用Flow版DAO,可简化为:
override fun create(params: Unit): Flow<DataState<List<NotificationItemsResponse.NotificationItemData>>> { return notificationDao.readAllDataFlow() .map<List<NotificationItemsResponse.NotificationItemData>, DataState<List<NotificationItemsResponse.NotificationItemData>>> { DataState.Success(it) } .onStart { emit(DataState.Loading) } .catch { emit(DataState.Error(it)) } }
3. 修改ViewModel层代码
你当前定义的notificationData类型和接收的DataState类型不匹配,需要调整类型定义:
// 调整为DataState包裹的类型 val notificationData = MutableStateFlow<DataState<List<NotificationItemsResponse.NotificationItemData>>>(DataState.Loading) fun getActualState() { viewModelScope.launch { getNotificationListItemDetailsUseCase.build(Unit).collect { notificationData.value = it Log.d("test2", "${notificationData.value}") } } }
4. 修改Fragment层代码
修复重复订阅问题,替换风险API:
- 不要使用
GlobalScope,改用lifecycleScope避免内存泄漏 - Success分支不需要重新collect flow,直接取返回的data赋值即可
viewLifecycleOwner.lifecycleScope.launch { collectNotificationItems() } private suspend fun collectNotificationItems() { vm.notificationData.collectLatest { dataState -> when(dataState) { is DataState.Error -> { collectErrorState() Log.d("collectNotificationItems", "Collect ErrorState") } DataState.Loading -> { Log.d("collectNotificationItems", "Collect Loading") } is DataState.Success<List<NotificationItemsResponse.NotificationItemData>> -> { notificationAdapter.items = dataState.data notificationAdapter.notifyDataSetChanged() Log.d("collectNotificationItems", "Collect Success") } } } }
额外优化建议
- Success分支的泛型尽量指定具体类型,避免用通配符
*减少类型转换风险 - 列表更新推荐用
DiffUtil代替notifyDataSetChanged,提升性能和动画效果
内容的提问来源于stack exchange,提问作者chrisu.chrisu
相关产品推荐
相关产品推荐

