34

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!

Remo
  • 1,112
  • 2
  • 12
  • 25
  • 1
    It should work with a `MutableStateList`. Use var `favourites by mutableStateListOf()` – Gabriele Mariotti Apr 25 '21 at 11:31
  • Thanks for your input! Is this also possible for a Set? I can't find any implementation... – Remo Apr 25 '21 at 13:47
  • 2
    Sets are not ordered and therefore do not implement `List` nor `Array` 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 Apr 27 '21 at 18:39

3 Answers3

52

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 = remember { mutableStateListOf<Track>()}

instead of

var favourites: MutableList<Track> by mutableStateOf(mutableListOf())
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
9

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
 
Santanu Sur
  • 10,997
  • 7
  • 33
  • 52
2

If you want to use mutableStateMapOf(), you can do like this

    val setData = remember { mutableStateMapOf("1" to "Jayant","2" to "Manish") }

    Text(text = "${setData["1"]}")

Output

Jayant
Jayant Kumar
  • 775
  • 5
  • 12