Home > OS >  Jetpack Compose not updating / recomposing Flow List Values from Room DB when DB Data is getting cha
Jetpack Compose not updating / recomposing Flow List Values from Room DB when DB Data is getting cha

Time:07-21

I'm trying to show a List of Items in my Android App. I'm using Jetpack Compose, Flows and RoomDB.

When launching the Activity all Items are shown without any problems, the Flow get's items collected and they are displayed.

But when I change some properties of the Item in the Database, the changes are not displayed. In my case I change the item to deleted, but it's still displayed as not deleted.

When I look at the Database Inspector, the value is changed in the database and set to deleted. When I log collecting the flow, the change is getting emitted (It says the Item is set to deleted) But Jetpack Compose is not recomposing the change.

If I delete an element from / add an element to the List (in the DB) the UI gets updated and recomposed.

So I can only assume that the problem must lie in the recomposition or handling of the flow.

Here my Code:

My Activity:


@AndroidEntryPoint
class StockTakingHistoryActivity : ComponentActivity() {

    private val viewModel: StockTakingHistoryViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel.stockList = ...

        setContent {
                    LaunchedEffect(Unit) {
                        viewModel.getStockListItems(viewModel.stockList!!.uuid)
                    }

                    Surface(color = MaterialTheme.colors.background) {
                        Content(viewModel.stockListItems)
                    }

            }
        }
    }
...
    @Composable
    private fun Content(items: List<StockListItem>) {
            ...
                LazyColumn {
                    items(items) { item ->
                        HistoryItem(stockListItem = item)
                    }
                }
        }

    }
...
    @Composable
    private fun HistoryItem(stockListItem: StockListItem) {
        ...
        Text(text = stockListItem.deleted)
        ...
        Button(onClick = {
            viewModel.deleteItem(stockListItem)
        }) {
            Text(text = "Set to deleted!")
        }
                                    

    }
}

My ViewModel:

    var stockListItems by mutableStateOf(emptyList<StockListItem>())

    fun getStockListItems(uuid: String) {
        viewModelScope.launch {
            stockListItemRepository.findByUUID(uuid).collect { items ->
                Log.d("StockTakingHistoryViewModel", "items changed! ${items.map { it.deleted }}")
                stockListItems = items
            }
        }
    }
    fun deleteItem(stockListItem: StockListItem) {
        viewModelScope.launch(Dispatchers.IO) {
            stockListItemRepo.update(item.copy(deleted = true);
        }
    }

The Repository:

    fun findByUUID(uuid: String): Flow<List<StockListItem>> {
        return dao.findByUUID(uuid)
    }

The Dao behind the Repository Request:

    @Query("select * from StockListItem where stockListUUID = :uuid order by createdAt desc limit 30")
    fun findByUUID(uuid: String): Flow<List<StockListItem>>

I would be very happy if someone could help me! Thank you!

CodePudding user response:

Considering you can collect a flow as state (via collectAsState) I'd consider going that route for getting the list rather than calling collect in the viewModel and updating the stockListItems as there are fewer moving parts for things to go wrong.

For example something like the following:

setContent {

    val stockListItems = viewModel.getStockListItemsFlow(uuid).collectAsState(initial = emptyList())
    
    Surface(color = MaterialTheme.colors.background) {
        Content(stockListItems)
    }
}

CodePudding user response:

Found the Problem: The equals() method of StockListItem only compared the primary key.

  • Related