Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unlike Livedata, using Flow in Room query doesn't trigger a refresh when updating a table entry but works if I delete or insert an entry

When using Livedata as a return type for a select* query on a table in Room, then I observe on it, I get triggers if I update/insert/delete an entry in that table. However, when I tried using Kotlin Flow, I only get 2 triggers.

The first trigger gives a null value as the initial value of the stateflow is a null. The second trigger is the list of entries in the Room table.

If I perform an insert/delete action on the DB, I receive a trigger from the StateFlow. However, If I update an entry, the Stateflow doesn't trigger.

N.B: The update operation works correctly on the DB. I checked using DB inspector.

Data class & 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)
}

ViewModel

val cartItems: StateFlow<List<CartItem>?> =
        repo.fetchCartItems().stateIn(viewModelScope, SharingStarted.Lazily, null)

Fragment

viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.cartItems.collect {
              Log.e("Update","Update")
 }
like image 569
Mena Avatar asked Oct 17 '25 03:10

Mena


1 Answers

My pitfall was that I was updating the object like this:

 currentItem.itemQuantity = currentItem.itemQuantity + 1
 changeQuantity(currentItem)

(currentItem is an object of class CartItem which is received initially from the getAllItems Flow in the DAO.)

(changeQuantity fun calls the changeQuantityInCart fun in the DAO.


This caused the reference of the CartItem object in the StateFlow to hold the updated value of the object with the new itemQuantity value before calling the update on the DB.

After that, when calling the Update fun in the DAO, the DB entry is updated and the Flow value changes, but when putting it in the Stateflow no changes are detected. Thus, the stateflow doesn't trigger as it is how stateflows differ from livedata.

In the case of livedata, it will trigger regardless if the new value is the same or not.

Thus, to solve this bug do not change the value of the object in the stateFlow before calling a DB update operation like this:

val updatedCartItem = cartItem.copy(itemQuantity = cartItem.itemQuantity + 1)
changeQuantity(updatedCartItem)
like image 79
Mena Avatar answered Oct 18 '25 18:10

Mena



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!