欢迎光临散文网 会员登陆 & 注册

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

2023-09-10 17:30 作者:スレーブ_スレイヤー  | 我要投稿


这是一个启动旋转动画的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



【安卓开发】问题记录,关于LaunchedEffect的调用,以及Composable的跳过的评论 (共 条)

分享到微博请遵守国家法律