Jetpack compose lazy column not recomposing with list
P

1

6

I have a list which is stored inside a Viewmodel via Stateflow.

class FirstSettingViewModel : ViewModel() {

     private val _mRoomList = MutableStateFlow<List<InitRoom>>(mutableListOf())
     val mRoomList: StateFlow<List<InitRoom>> = _mRoomList
    
     ...

I observe the flow via collectAsState(). The LazyColumn consists of Boxes which can be clicked.

val roomList = mViewModel.mRoomList.collectAsState()

Dialog {

    ...

    LazyColumn(...) {

        items(roomList.value, key = { room -> room.room_seq}) { room ->
          
           Box(Modifier.clickable {
              **mViewModel.selectItem(room)**
           }) {...}
       }
    }
}

When a click event occurs, the viewModel changes the 'isSelected' value via a copied list like this.

fun selectItem(room: InitRoom) = viewModelScope.launch(Dispatchers.IO) {
    try {
        val cpy = mutableListOf<InitRoom>()
        mRoomList.value.forEach {
            cpy.add(it.copy())
        }
        cpy.forEach {
            it.isSelected = it.room_seq == room.room_seq
        }
        _mRoomList.emit(cpy)
    } catch (e: Exception) {
        ErrorController.showError(e)
    }
}

When in an xml based view and a ListAdapter, this code will work well, but in the above compose code, it doesn't seem to recompose the LazyColumn at all. What can I do to re-compose the LazyColumn?

Ptah answered 7/11, 2022 at 8:12 Comment(0)
G
3

Use a SnapshotStateList instead of an ordinary List

change this,

private val _mRoomList = MutableStateFlow<List<InitRoom>>(mutableListOf())
val mRoomList: StateFlow<List<InitRoom>> = _mRoomList

to this

private val _mRoomList = MutableStateFlow<SnapshotStateList<InitRoom>>(mutableStateListOf())
val mRoomList: StateFlow<SnapshotStateList<InitRoom>> = _mRoomList
Goraud answered 7/11, 2022 at 8:25 Comment(5)
It works, but I really don't get what's going on. My logic makes one item's isSelected state to true, and others to false. I thought it will only recompose two lazyColumn items, but it seems that all the visible items inside the lazy column is recomposed. Is this a normal case?Ptah
If you are using at least Dolphin, you can check the re-composition count from the Layout Inspector.Goraud
I added a log inside the items lambda to print the key of the item when it's being called. Isn't this the recompose?Ptah
Thanks a lot :) This solved my problem in LazyVerticalGrid as well. I had similar problem where despite of adding items in ArrayList, it would not recomposeRedeeming
Isn't this overkill? Shouldn't we just use SnapshotStateList and disregard MutableStateFlow?Bogbean

© 2022 - 2024 — McMap. All rights reserved.