带有KotlinFlow toList()的Android房间库不工作

kdfy810k  于 2023-02-02  发布在  Android
关注(0)|答案(5)|浏览(198)

我使用Room和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()工作正常,给我所有的记录。
有谁能给我解释一下怎么回事?谢谢。

wvyml7n5

wvyml7n51#

这里有几件事是错的,但我会解决主要问题。
由room返回的Flow s在每次修改数据库时发出查询结果。(这可能限于表更改,而不是整个数据库)。
由于数据库可能在将来的任何时候发生更改,因此Flow将(或多或少)永远不会完成,因为更改总是可能发生的。
对返回的Flow调用toList()将永远挂起,因为Flow永远不会完成。这在概念上是有意义的,因为Room无法在不等待它发生的情况下给予您将要发生的每个更改的列表。有了这个,我相信您知道为什么collect给您记录,而toList()不给您。
你可能需要这个。

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

这样就可以得到Flow<...>.first()查询的第一个结果。

fdbelqdn

fdbelqdn2#

室内流动是为了观察表中的变化。
无论何时对表进行任何更改,无论更改的是哪一行,都会重新触发查询并再次发出Flow。
然而,数据库的这种行为也意味着,如果我们更新一个不相关的行,我们的Flow将再次发出,结果相同。因为SQLite数据库触发器只允许在表级别而不是行级别进行通知,所以Room无法确切地知道表数据中发生了什么变化

sq1bmfud

sq1bmfud3#

确保您用于检索列表的同一doa对象用于更新数据库。除此之外,将流转换为livedata是使用asLivedata扩展函数完成的

k97glaaz

k97glaaz4#

对于我来说,下面的解决方案适用于使用数据库表更改来更新视图。
解决方案:当我们将详细信息插入房间数据库并从DB中获取信息时,应该使用相同的Dao对象。
如果你用的是匕首柄
@Singleton注解将起作用。
我希望这能解决你的问题。

rfbsl7qr

rfbsl7qr5#

**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

相关问题