Jan Veselý
Jan Veselý

Reputation: 1519

Livedata don't update compose state when list item property has changed

My problem is that live data observer is triggered Observer<T> { state.value = it } with the correct data but compose doesn't kick on recompose. Only when I add an item all changes are propagated. There must some checking on the list itself if it has changed. I guess it doens't compare list items.

@Composable
fun <R, T : R> LiveData<T>.observeAsState(initial: R): State<R> {
    val lifecycleOwner = LifecycleOwnerAmbient.current
    val state = remember { mutableStateOf(initial) }
    onCommit(this, lifecycleOwner) {
        val observer = Observer<T> { state.value = it }
        observe(lifecycleOwner, observer)
        onDispose { removeObserver(observer) }
    }
    return state
}

val items: List<TrackedActivityWithMetric> by vm.activities.observeAsState(mutableListOf())
 LazyColumnForIndexed(
        items = items,
        Modifier.padding(8.dp)
    ) { index, item ->
    ....
    MetricBlock(item.past[1], item.activity.id )

}

Upvotes: 4

Views: 4046

Answers (2)

Jetpack Compose does not work well with MutableList, you need to use a List and do something like this:

var myList: List<MyItem> by mutableStateOf(listOf())
    private set

for adding an item:

fun addItem(item: MyItem) {
    myList = myList + listOf(myItem)
}

for editing an item:

fun editItem(item: MyItem) {
    val index = myList.indexOf(myItem)
    myList = myList.toMutableList().also {
        it[index] = myItem
    }
}

Upvotes: 2

Jan Vesel&#253;
Jan Vesel&#253;

Reputation: 1519

So behind the scenes there must be some kind hash comparing mechanism preventing rendering same item twice (More elabored answer wanted). The incorrect rendering was caused by property which was not in TrackedActivityWithMetric data class constructor.

Upvotes: 3

Related Questions