https://kotlinlang.org logo
#compose
Title
# compose
t

Thiago

11/30/2020, 12:53 PM
Playing with recomposition to understand the optimistic scenario, I discovered that I can create a simple bouncing ball without any animation api. Just changing mutable state values. Is that a thing to avoid or is perfectly fine? About hardware resources can things like that consume a lot?
z

Zach Klippenstein (he/him) [MOD]

11/30/2020, 1:56 PM
This makes sense since, at least right now, there’s a 1:1 relationship between frames and compositions (composition is triggered every frame, and only by the frame), and MutableState changes that happen in one frame will immediately mark the recompose scope as dirty for the next frame, causing a loop. However I think this is probably not great because compositions can fail, and so you could theoretically skip some animation frames if a failed composition causes your code to run multiple times per frame. I’m not sure if you’d ever notice that currently, but I think this could start breaking once composition starts getting automatically split across threads.
That said, you can get something very similar with
LaunchedEffect
and
awaitFrame
in a loop
t

Thiago

11/30/2020, 2:14 PM
This sample I ran first with compose desktop. I didn't saw any frame drops. Then I executed with Android Emulator and I saw some dropped frames when the ball falling. Good to know about 1:1. What is the best way to fix frame drop in the sample?
j

Joost Klitsie

11/30/2020, 2:20 PM
Well usually you put in a time factor, or something that is based on time. So you don't say 20 pixels per frame as you will not know what your framerate will be, but you can say 200px per second. In that case, you calculate time passed since last frame and multiply it by the 200px per second
also I don't think you have to remember constant values
😅 1
☝️ 1
z

Zach Klippenstein (he/him) [MOD]

11/30/2020, 2:32 PM
Good to know about 1:1
Don’t quote me on that, and don’t rely on it 😜 I think that it’s usually 1:1 currently but I don’t believe that’s part of the contract so it’s not safe to rely on for stuff like this. If you are actually building real animations and not just exploring the tech, definitely use the actual animation apis.
a

Adam Powell

11/30/2020, 3:30 PM
The body of a
Canvas
isn't run during composition, it's run during the drawing phase. It's correct that something might be drawn multiple times for a single frame in some potentially esoteric cases
I also don't see any code here that would guarantee that repeated invalidation should occur and that this should redraw on every frame. If anything, if this code works I think we have a bug to fix in that state changed within the body of a drawing handler like
Canvas
should not invalidate that same drawing handler to produce a subsequent frame
All that is to say, use
LaunchedEffect
and
withFrameNanos
(not the
kotlinx.coroutines
awaitFrame
!) to run a loop that updates your state based on time
t

Thiago

11/30/2020, 5:49 PM
I think that I'm entering in the advanced compose with
LaunchedEffect
and
withFrameNanos
😅. Constant remembers was a mistake after a refactor. I'll check them out.
29 Views