问题描述
当在 Room 中的表上使用 Livedata 作为 select* 查询的返回类型时,我观察它,如果我更新/插入/删除该表中的条目,我会得到触发器。但是,当我尝试使用 Kotlin Flow 时,我只有 2 个触发器。
第一个触发器给出一个空值,因为 stateflow 的初始值为空。第二个触发器是 Room 表中的条目列表。
如果我对数据库执行插入/删除操作,我会收到来自 StateFlow 的触发器。 但是,如果我更新条目,Stateflow 不会触发。
注意:更新操作在数据库上正常工作。我使用数据库检查器进行了检查。
数据类和 DAO
@Entity
data class CartItem (
@PrimaryKey
val itemId: Int,var itemQuantity: Int=1
)
@Dao
interface CartDao {
@Query("SELECT * FROM CartItem")
fun getAllItems(): Flow<List<CartItem>>
@Update
suspend fun changeQuantityInCart(cartItem:CartItem)
@Insert
suspend fun insert(item: CartItem)
@Delete
suspend fun delete(cartItem:CartItem)
}
视图模型
val cartItems: StateFlow<List<CartItem>?> =
repo.fetchCartItems().stateIn(viewmodelScope,SharingStarted.Lazily,null)
片段
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
viewmodel.cartItems.collect {
Log.e("Update","Update")
}
解决方法
我的缺陷是我正在像这样更新对象:
currentItem.itemQuantity = currentItem.itemQuantity + 1
changeQuantity(currentItem)
(currentItem
是 CartItem
类的对象,最初从 DAO 中的 getAllItems
流接收。)
(changeQuantity
fun 调用 DAO 中的 changeQuantityInCart
fun。
这导致 StateFlow 中 CartItem 对象的引用在调用 DB 上的更新之前使用新的 itemQuantity 值保存对象的更新值。
此后,在 DAO 中调用 Update fun 时,会更新 DB 条目并更改 Flow 值,但将其放入 Stateflow 时未检测到任何更改。因此,状态流不会触发,因为状态流与实时数据不同。
对于livedata,无论新值是否相同都会触发。
因此,要解决此错误,请在调用数据库更新操作之前不要更改 stateFlow 中对象的值,如下所示:
val updatedCartItem = cartItem.copy(itemQuantity = cartItem.itemQuantity + 1)
changeQuantity(updatedCartItem)