带有Kotlin Flow toList()的Android Room库不起作用

带有Kotlin Flow toList()的Android Room库不起作用,android,android-room,kotlin-coroutines,kotlin-flow,Android,Android Room,Kotlin Coroutines,Kotlin Flow,我制作了一个使用Room and Flows的简单示例应用程序: class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val build = Room.databaseBuilder(th

我制作了一个使用Room and Flows的简单示例应用程序:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val build = Room.databaseBuilder(this, FinanceDatabase::class.java, "database.db")
            .fallbackToDestructiveMigration()
            .build()
    GlobalScope.launch {
        build.currencyDao().addCurrency(CurrencyLocalEntity(1))
        val toList = build.currencyDao().getAllCurrencies().toList()
        Log.d("test", "list - $toList")
    }
}
}

@Entity(tableName = "currency")
data class CurrencyLocalEntity(
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "currencyId")
        var id: Int
) {
    constructor() : this(-1)
}

@Dao
interface CurrencyDao {

@Query("SELECT * FROM currency")
fun getAllCurrencies(): Flow<CurrencyLocalEntity>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addCurrency(currency: CurrencyLocalEntity)
}

@Database(entities = [CurrencyLocalEntity::class], version = 1)
abstract class FinanceDatabase : RoomDatabase() {
    abstract fun currencyDao(): CurrencyDao
}
我想在上面的代码中使用toList函数,但出现了一些错误,甚至日志也无法打印。同时使用collect可以很好地工作,并给我所有的记录


谁能给我解释一下怎么了?谢谢。

房间里的水流是用来观察桌子上的变化的

无论何时对表进行任何更改(与更改的行无关),都将重新触发查询,并且流将再次发出


然而,数据库的这种行为也意味着,如果我们更新一个不相关的行,我们的流将再次发出,并产生相同的结果。因为SQLite数据库触发器只允许在表级别而不允许在行级别发出通知,所以Room无法确切地知道表数据中发生了哪些更改,这里有一些错误,但我将解决主要问题

**getAllCurrencies()** function should be suspend.

Please check the syntax to collect List from Flow: 

suspend fun <T> Flow<T>.toList(
    destination: MutableList<T> = ArrayList()
): List<T> (source)

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-list.html
每次修改数据库时,文件室返回的流都会发出查询结果。这可能是表更改的范围,而不是整个数据库

由于数据库在将来的任何时候都可能发生更改,因此流或多或少都不会完成,因为更改总是可能发生的

返回流上的调用toList将永远挂起,因为该流永远不会完成。这在概念上是有意义的,因为Room不能在不等待更改发生的情况下为您提供将要发生的每个更改的列表。 有了这个,我相信你知道为什么collect会给你这些记录而toList不会

你可能想要的是这个

@查询从货币中选择* 有趣的货币:流动
这样,您就可以使用Flow.first获得查询的第一个结果。

确保用于检索列表的同一doa对象用于更新数据库。
除了使用asLivedata扩展函数将流转换为livedata之外,还建议当您希望从生成多个项的查询返回流时,应使用流。返回流的示例用于返回单个项的查询。您的GetAllCurrences需要为currency表中的每个项目释放空间。我认为它不支持这一点。如果我们将first与flow一起使用,那么表更改不会再次调用第一个{}块。但是如果我们使用collect{},那么任何表更改都会调用collect{}。你认为我们可以在第一个{}中继续得到表的更改吗?第一个给你第一个更改。如果要获取将来的更改,请使用collect。