【安卓开发】问题记录,关于LaunchedEffect的调用,以及Composable的跳过

这是一个启动旋转动画的LaunchedEffect,当状态改变成播放,就会被重启,设置之前记录的播放进度,开始无限旋转。
本来这段代码完美地执行着,但是在我修改了布局结构以后,LaunchedEffect就开始直接不调用了,就让人有点匪夷所思,花了一个晚上差不多把原因搞清楚了。
我的第一个反应肯定是没有触发重组,因为LaunchedEffect是在重组完成时调用的,而Compose的会尽量跳过不必要的重组,打了日志一看,果然是这样。
但是以前并没有这个问题,在经过各种控制变量以后,我确信问题出在一个地方:
调试。
调试模式跟发布模式,Compose的行为以及性能会有一些变化,我上一次遇到过一样的问题,但是发布模式编译以后就没问题了,所以就没管。
本来是这么想的。但是这次,就算以发布模式编译,最终还是有问题。
最后唯一的变量就是,我更新了Compose的版本,用的是最新的测试版,以前用的是2022年3月的稳定版。然后我想了想,可能以前的代码能够运行,是一个BUG呢?
Compose判断一个Composable能否被重组,是通过参数有没有改变,而对于我最外层的Composable来说,参数一定是不变的。只是,常识上大家都把LaunchedEffect写在最外层,就觉得只能这样,所以
解决方案1:
把LaunchedEffect移到内层。最终这么做了以后,成功解决了,但就总还是不够优雅。
于是解决方案2:
自己开协程。LaunchedEffect的执行一定在我点击按钮以后,那我直接在onClick里面开协 程,做一样的操作就行了。这个方案也行,但是不方便管理,约定好所有动画的控制都使用LaunchedEffect比较好。
于是解决方案3:
更改key。LaunchedEffect自身也是一个Composable,它自身参数的变化也会触发重组,
那我给一个state做key就好了。然后完美解决。
这里我想强调的是,我以前对Compose的跳过是模糊的,不知道哪些组件会被跳过,哪些不会,但是现在很明确了:
参数值不变的Composable就会被跳过。
明确理解了这一点以后,我才有了解决方案3,所以写下来强化一下记忆。
参考资料:
https://skyyo.medium.com/performance-in-jetpack-compose-9a85ce02f8f9
https://chrisbanes.me/posts/composable-metrics/#default-parameter-expressions-that-are-dynamic
https://juejin.cn/post/7110208846051672095