4
votes

I've got a composable on a Screen which shows a list of Track items (favourites) :

var favourites: MutableList<Track> by mutableStateOf(mutableListOf())
@ExperimentalFoundationApi
@Composable
private fun ResultList(model: FreezerModel) {
    with(model) {
        if (favourites.isEmpty()) NoDataMessage("No favourites yet")
        else {
            LazyColumn(state = rememberLazyListState()) {
                items(favourites) {
                    TrackCard(it, model)
                }
            }
        }
    }
}

On click events, I am updating my favourites list (add/remove item). How can I make my composable reflect these changes immediately (like to re-draw itself or something similar)? So far, it only works when I first switch to another screen.

Thanks for your inputs!

2
It should work with a MutableStateList<T>. Use var favourites by mutableStateListOf<Track>()Gabriele Mariotti
Thanks for your input! Is this also possible for a Set? I can't find any implementation...Remo
Sets are not ordered and therefore do not implement List<T> nor Array<T> supported by items() and are therefore cannot be used as a parameter to items() directly. In this case, calling toList() on the set every time is updated would work.chuckj

2 Answers

9
votes

You need to use a MutableStateList<T> so that Compose can automatically recompose when the state changes.

From official doc:

Caution: Using mutable objects such as ArrayList<T> or mutableListOf() as state in Compose will cause your users to see incorrect or stale data in your app.

In your code use

val favourites by mutableStateListOf<Track>()

instead of

var favourites: MutableList<Track> by mutableStateOf(mutableListOf())
3
votes

Just removing state = rememberLazyListState() from the lazyColumnFor params list should work in your case.

According to the doc if we use rememberLazyListState() then :-

Changes to the provided initial values will not result in the state being recreated or changed in any way if it has already been created.

After doing so , normally updating the list should work fine. Also its a good practice to expose an immutable list ( list ) instead of a mutableList to the composable.

For example use:-

var favourites by mutableStateOf(listOf<FavoriteItem>())

then add/remove/update the list by using :-

favourites = favourites + newList // add 
favourites = favourites.toMutableList().also { it.remove(item) } // remove