Kacper
03/01/2024, 12:53 PMLazyRow(state = lazyRowState) {
items(
items = items,
key = { state -> state.id }
) { state ->
SomeCard(
state = state,
onClick = {
state.onClick(state.id)
}
)
}
}
The items are of type ImmutableList<SomeState>
and state.onClick
makes it so the reducer updates one of the items to be expanded (copying and assigning). When I click on any of the cards it makes all of the cards to recompose. When going to debug mode and looking at what changes I see that state
is unchanged but the onClick
is changed every time for every SomeCard
item. Adding remember (state) { ... }
before the lambda fixes the problem, and here comes the question. Shouldn't compose compiler do it automatically? I have read that this is his default behavior in this kind of situations when the value is of stable type.
Leaving the LazyRow behind and just experimenting with forEach
loop gives the same results.Stylianos Gakis
03/01/2024, 1:11 PMSomeState
not a stable type? If your lambda is capturing a non stable reference, it will not be remembered automatically in the current version of composeKacper
03/01/2024, 1:13 PMdata class SomeState(
val id: String,
val clockTime: String,
val isExpanded: Boolean,
val onClick: (id: String) -> Unit
)
Kacper
03/01/2024, 1:14 PMStylianos Gakis
03/01/2024, 1:21 PMAnd for the love of god I cannot reproduce it in a sample project I have for this types of questions 😅Don’t we all 😅
Stylianos Gakis
03/01/2024, 1:22 PMSean Proctor
03/01/2024, 1:26 PM@Immutable
and see if that helps.Kacper
03/01/2024, 1:33 PM@Immutable
hell, even @Stable
(which is actually the same xD) fixes the issue... Is my SomeState
not stable?!? It has only stable types inside. What the hell... I will pull out the big guns and check compose compiler reports but thats strange as hellSean Proctor
03/01/2024, 1:34 PMSean Proctor
03/01/2024, 1:36 PMList
in there. You need to use immutable types not just val
instead of var
.Sean Proctor
03/01/2024, 1:37 PM@Stable
means that the value can be changed, but that you will notify on changes. I don't think that is the case here.Kacper
03/01/2024, 2:56 PMstable class SomeState {
stable val id: String
stable val clockTime: String
stable val isExpanded: Boolean
stable val onClick: Function1<@[ParameterName(name = 'id')] String, Unit>
<runtime stability> = Stable
}
even without annotations haha. Really strange, seams that only annotation force compose compiler to remember the lambda. Maybe its some kind of bug, or just I don't see something trivial. Who knows. I hope strong skipping
will resolve like 90% of those issues in the future ;DKacper
03/01/2024, 2:56 PMSean Proctor
03/01/2024, 2:58 PMStylianos Gakis
03/01/2024, 3:00 PMKacper
03/01/2024, 3:26 PMviewModelScope
dispatcherProvider
reducer
but I see that dispatcherProvider is unstable, so I got rid of it and make it pass empty function like
private fun onClick(id: String) {
}
to the state object. Event then when I recompose manually the parent composable the onClick reports that it changedKacper
03/02/2024, 11:55 AM@Stable/@Immutable
when they are in other modules to be sure that they wont cause recomposition where they shouldn't.Stylianos Gakis
03/02/2024, 12:01 PM