`AnimatedContent` is not animating my content in a...
# compose
z
AnimatedContent
is not animating my content in a given scenario, despite
targetState
having changed. It works in all other cases. Any ideas? More details in 🧵
Ive added logs to verify that the targetState does in fact change, that transitionSpec is invoked and results in the animations I want, and that the content block is invoked with the new content. (Ill add those logs at the end in case theyre helpful). For this particular case, Im viewing a details screen, choosing to delete the data that it represents - which in turn causes the screen to be hidden (which is where the animation should play). The animation runs perfectly fine if I just navigate back without deleting the data, and the delete does cause the parent screen to reload its data - but all of that happens in the background, so I dont really see how that could play a role in this? Once the animation is "done", i.e. jumps to its final state, everything works like normal again, so its literary just the animation itself not running for some unknown reason. Here are the logs; 1 represents the parent, 2 is the details screen. targetState(1) exit() exit() content(2) exit() exit() content(1) content(2) content(1) content(1) content(1) content(1) content(1) My animations are really simple, using
slideInVertically + fadeOut
and
slideOutVertically + fadeIn
.
i
Note that composition keeps happening even while your animation is happening, so your details screen will continue to be recomposed as your animation runs. That means that it'll continue to be recomposed even after you've deleted the data it is displaying. What does your details screen emit if there is no underlying data in whatever source of truth you are loading your data from? If, for example, it something like a
collectAsState()
then an
if (data != null) { DetailScreen(data) }
, then you'll just be animating out an empty screen, which doesn't seem like what you'd want
z
It holds the last known value in its state (in a viewmodel of sorts), so nothing really changes there.
The loading itself is delivered as a Result<T>, so I just do result.onSuccess { updateState }.onFailure { navigateBack }
Just for sanity, I ran through the loop and I can verify that the correct state is being rendered even on the way out! If I specify
dataFlow.take(1)
on the parent, then the animations runs fine 🤷🏽‍♂️ So definitely seems to be related to that, but I cant tell how. Ive gone through the entire loop multiple times and everything works exactly as expected.. basically: delete happens, cache is updated, triggers related flows to refresh, screen is updated.
i
in that
result.onSuccess { updateState }.onFailure { navigateBack }
call, did you log how many times the
onSuccess
and
onFailure
lambdas are being called? It would be interesting to know if you're somehow calling
navigateBack
multiple times in a row
z
I found the issue! I dont fully understand how it could have an impact on this, but the gist of it is that my repository had a
withContext(IO)
block, and the result of that was then handled inside another
withContext(IO)
block (my intention was to have both of those in the same block). Theres literary no code outside the withContext blocks, and the entire call is invoked on
Dispatchers.Default
. Id love to understand how that could have such an impact on this scenario! I also understand if thats impossible to say without way more details, all in all Im just glad that it works as expected 🙂