Hey there! :wave: I have a `LazyColumn` which cont...
# compose
w
Hey there! 👋 I have a
LazyColumn
which contains a
ChatItem
and that item contains a
TypingText
Composable (attached to the snippet) and every time I scroll the list when the item is recycled and visible again, the
TypingText
is recomposed, so the typing text effect is relaunched causing an undesired experience. I have made all the composables
skippable
and
restartable
as I can see in the compose report. Also, there are no more unstable parameters or collections. The list contains an unique key assigned, but this continues recomposing. Is there anything I can do for that? I'd appreciate your thoughts.
s
Getting an extra recomposition should not result in wrong behavior ever. You are calling a side effect,
onTextChange
in composition, you should never do that.
From https://developer.android.com/develop/ui/compose/side-effects#state-effect-use-cases
Copy code
composables should be side-effect free. When you need to make changes to the state of the app (as described in the Managing state documentation doc), you should use the Effect APIs so that those side effects are executed in a predictable manner.
edit: I just saw your
onTextChange
was a Composable lambda itself. The lowercase text + its name made me think it's not composable, sorry about that.
w
before having the
onTextChange
I had the
Text
directly there, but that still does not work 😕
s
What does "still does not work" mean in that case? And what did the code look like in the alternative way you had it?
w
This is the original code. Still does not work means it is still recomposing, launching the effect when the item is again visible in the list
looking at the compose compiler report it looks like this:
everything looks good, but still it is recomposing
s
And how do you provide these items in your lazy list dsl? The docs here say:
Copy code
When you provide the contentType, Compose is able to reuse compositions only between the items of the same type. As reusing is more efficient when you compose items of similar structure, providing the content types ensures Compose doesn't try to compose an item of type A on top of a completely different item of type B. This helps maximize the benefits of composition reusing and your Lazy layout performance.
Make sure you do that too
w
ohh, I have not considered it. Let me try it out. Thank you Stylianos
I have provided to the
LazyColumn
the contentType without luck
Untitled.kt
I'm wondering if it is the nature of the lazy list, to recompose the items that have been recycled 🤔 in that way, the animation has to be restarted every time, because if it is saved somewhere the Laziness, from my perspective, would not have sense, because it has to save the state of every item and that is not a good idea .. now, I'm thinking how to ensure, on the contrary, if the composable can be skipped if it is the same
I also tried adding the annotation
@NonRestartableComposable
which is not that good idea, but just in case, but that does not work either.
I tried with a simple list, with the same result .. so that's why I'm thinking about the nature of the LazyList
typing-text-recomposing.mp4
I think this should be part of the StateHolder, the ViewModel 😕 that would not look good but i think it is like that as a business rule, it has to type text only when it is a new message to the chat.
s
Yeah to be 100% honest, I'm not sure if it should be able to skip that in the first place. If nobody else answers here who knows better how lazy lists work, you'd probably have to lift this information outside of the UI like that, and store if you wanna play this animation or not somewhere where it does not care of if things are reused in the lazy list or not.
w
I'll continue trying other alternatives. Thank you Stylianos for taking care of this 🙂
also, I can see if the Modifier can help on this 🤔
I found a solution for this, but that is not so beautiful 😄 .. since the scrolling is causing a recomposition every time, so I created a remember outside the list:
Copy code
val displayedChats = remember { mutableStateMapOf<String, String>() }
and the chats displayed, are stored there, if the message was already displayed, then it is not going to run the typing effect since the text did not change. 😳
a
On scroll, lazy list recomposes items(with some prefetching), and discards those items when the LazyList item goes out of the bounds of the view. For anything, that you want to store you have to store those either in ViewModel or ViewStateHolder
m
maybe rememberSaveable with a flag or something to check if it was animated once would work