Flow的collect函数是Kotlin中的block函数吗?
Is the collect function of Flow a block function in Kotlin?
希望用Room删除Id列表和相关文件的记录
我发现当我运行代码A
时,文件可以删除,记录不能删除
我发现我运行代码B时可以删除记录
好像Log.e("My","Fire")
在代码A里没有推出,不知道为什么?
Q1:代码A有什么问题?
Q2:我使用Flow时collect
是块函数吗?
Q3:fun getByID(id:Int): Flow<RecordEntity?>
是好的设计吗?也许应该是 fun getByID(id:Int): RecordEntity?
.
代码A
class RecordRepository @Inject constructor(
private val mRecordDao:RecordDao
) {
override fun getByID(id:Int): Flow<MRecord?> = mRecordDao.getByID(id).map {it?.let{ModelMapper.entityToModel(it) } }
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
idList.forEach{
getByID(it).collect {
it?.let {
val filename = it.soundFileName
deleteFileOrFolder(filename)
}
}
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}
}
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table where id=:id")
fun getByID(id:Int): Flow<RecordEntity?>
@Query("delete from record_table where id in (:idList)")
suspend fun deleteRecord(idList: List<Int>)
}
代码B
class RecordRepository @Inject constructor(
private val mRecordDao:RecordDao
) {
override fun getByID(id:Int): Flow<MRecord?> = mRecordDao.getByID(id).map {it?.let{ModelMapper.entityToModel(it) } }
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
mRecordDao.deleteRecord(idList)
}
}
//The same
新增内容:
致 Arpit Shukla:谢谢!
我发现许多查询示例 return 使用代码 C 与 Room 流动数据。
我觉得Code D就够了,而且很简单
我很困惑为什么我需要在 Room 中使用 Flow,你知道我最多只想要一次实体,你能告诉我吗?
代码C
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table ORDER BY createdDate desc")
fun listRecord(): Flow<List<RecordEntity>>
}
代码D
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table ORDER BY createdDate desc")
suspend fun listRecord(): List<RecordEntity>
}
collect
函数永远挂起。它永远不会恢复。所以你放在 collect
之后的任何代码都不会被执行。这是代码A的问题。
如果你想让代码 A 工作,你应该使用 launch
函数在单独的协程中收集每个流。
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
idList.forEach {
launch {
getByID(it).collect {
it?.soundFileName?.let { deleteFileOrFolder(it) }
}
}
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}
此外,您无需在代码中切换 Dispatchers,Room 会自动完成。
编辑: 如果您只需要获取一次 RecordEntity
的列表,代码 D 是更好的方法。当我们需要观察查询结果的变化时,需要Flow
。例如,在 UI 中显示 RecordEntity
的列表时,如果数据库中的数据发生变化,我们希望更新 UI,为此我们可以 return Flow
来自道.
对于您的具体情况,您可以这样做:
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table where id=:id")
suspend fun getByID(id:Int): RecordEntity?
}
override suspend fun deleteRecord(idList: List<Int>) {
idList.forEach { id ->
getByID(id)?.soundFileName?.let { deleteFileOrFolder(it) }
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}
希望用Room删除Id列表和相关文件的记录
我发现当我运行代码A
时,文件可以删除,记录不能删除我发现我运行代码B时可以删除记录
好像Log.e("My","Fire")
在代码A里没有推出,不知道为什么?
Q1:代码A有什么问题?
Q2:我使用Flow时collect
是块函数吗?
Q3:fun getByID(id:Int): Flow<RecordEntity?>
是好的设计吗?也许应该是 fun getByID(id:Int): RecordEntity?
.
代码A
class RecordRepository @Inject constructor(
private val mRecordDao:RecordDao
) {
override fun getByID(id:Int): Flow<MRecord?> = mRecordDao.getByID(id).map {it?.let{ModelMapper.entityToModel(it) } }
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
idList.forEach{
getByID(it).collect {
it?.let {
val filename = it.soundFileName
deleteFileOrFolder(filename)
}
}
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}
}
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table where id=:id")
fun getByID(id:Int): Flow<RecordEntity?>
@Query("delete from record_table where id in (:idList)")
suspend fun deleteRecord(idList: List<Int>)
}
代码B
class RecordRepository @Inject constructor(
private val mRecordDao:RecordDao
) {
override fun getByID(id:Int): Flow<MRecord?> = mRecordDao.getByID(id).map {it?.let{ModelMapper.entityToModel(it) } }
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
mRecordDao.deleteRecord(idList)
}
}
//The same
新增内容:
致 Arpit Shukla:谢谢!
我发现许多查询示例 return 使用代码 C 与 Room 流动数据。
我觉得Code D就够了,而且很简单
我很困惑为什么我需要在 Room 中使用 Flow,你知道我最多只想要一次实体,你能告诉我吗?
代码C
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table ORDER BY createdDate desc")
fun listRecord(): Flow<List<RecordEntity>>
}
代码D
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table ORDER BY createdDate desc")
suspend fun listRecord(): List<RecordEntity>
}
collect
函数永远挂起。它永远不会恢复。所以你放在 collect
之后的任何代码都不会被执行。这是代码A的问题。
如果你想让代码 A 工作,你应该使用 launch
函数在单独的协程中收集每个流。
override suspend fun deleteRecord(idList: List<Int>) = withContext(Dispatchers.Default) {
idList.forEach {
launch {
getByID(it).collect {
it?.soundFileName?.let { deleteFileOrFolder(it) }
}
}
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}
此外,您无需在代码中切换 Dispatchers,Room 会自动完成。
编辑: 如果您只需要获取一次 RecordEntity
的列表,代码 D 是更好的方法。当我们需要观察查询结果的变化时,需要Flow
。例如,在 UI 中显示 RecordEntity
的列表时,如果数据库中的数据发生变化,我们希望更新 UI,为此我们可以 return Flow
来自道.
对于您的具体情况,您可以这样做:
@Dao
interface RecordDao {
@Query("SELECT * FROM record_table where id=:id")
suspend fun getByID(id:Int): RecordEntity?
}
override suspend fun deleteRecord(idList: List<Int>) {
idList.forEach { id ->
getByID(id)?.soundFileName?.let { deleteFileOrFolder(it) }
}
Log.e("My","Fire")
mRecordDao.deleteRecord(idList)
}