如何用Kotlin Flow手动映射Room一对一关系且无需创建额外组合类
解决方案
方案1:使用挂起版CategoryDao(推荐,性能更优,适合分类变动少的场景)
你之前的问题核心有两点:
- 返回Flow的方法不需要加
suspend修饰,Flow是冷流,只有收集时才会执行逻辑,挂起修饰属于多余声明 - 自定义的
mapIterable扩展没有支持挂起函数转换
修改步骤: - 保留挂起版的CategoryDao定义:
@Dao interface CategoryDao { @Query("SELECT * FROM categories WHERE uid = :id") suspend fun get(id: Int): DatabaseCategory }
- 修改
mapIterable扩展,支持挂起转换逻辑:
inline fun <T, R> Flow<Iterable<T>>.mapIterable(crossinline transform: suspend (T) -> R): Flow<List<R>> = map { iterable -> iterable.map { item -> transform(item) } }
- 去掉Repository中getAll方法的
suspend修饰:
override fun getAll(): Flow<List<Transaction>> { return transactionDao .getAll() .mapIterable{ tx -> Transaction(tx, categoryDao.get(tx.categoryId)) } }
方案2:保留CategoryDao的Flow返回值(适合分类需要实时同步更新的场景)
如果需要分类修改时自动同步更新关联的交易列表,可以直接组合多个Flow实现关联,不需要修改Dao为挂起函数:
override fun getAll(): Flow<List<Transaction>> { return transactionDao.getAll() .flatMapConcat { transactions -> // 为每个交易生成对应的分类Flow,再组合所有Flow为列表 transactions.map { tx -> categoryDao.get(tx.categoryId) .map { category -> Transaction(tx, category) } }.combine { transactionList -> transactionList.toList() } } }
两种方案都不需要额外创建TransactionAndCategory关联类,完全符合你的要求。
内容的提问来源于stack exchange,提问作者DennisVA
相关产品推荐
相关产品推荐

