摘要
有许多基准比较了XML和compose的性能和渲染速度。在大多数情况下,它们都表明compose更快。然而,有人认为这些基准并没有给出一个完整的性能图景,因为它们比较的是一些琐碎的解决方案,如单一嵌套或缺乏大量的视图。也有人认为,在关键的情况下,如深或宽的视图嵌套,会有不同的结果。也有观点认为,在已经存在的大型项目中重构代码进行组合是没有意义的,因为混合变体**(组合+xml**)会在项目中存在很长时间,而且渲染性能会因此受到更大的影响。这就是为什么我决定比较更复杂的变体。
-深度和广度视图嵌套。
-**混合(compose+xml)**状态对这些情况的影响。
观察和假设
-这个比较绝不是声称对所有类型的设备、内存量或不同类型的显示器都是绝对正确的。
-测量是在小米mi 5s手机上进行的,MIUI Global 10.2,12.15GHz四核处理器,3GB RAM,Android 8.0。特别是选择了不是最强大和最高端的手机,这样差异就更明显了。大多数人使用类似的设备。
-为了减少代码量,我没有计算屏幕的密度,因为我知道我有3。
-使用Android Studio建议的16种颜色,将各视图分开。
-对每一种情况进行10次测量,并计算出平均值。-如果你有任何关于质量或数量的问题,每个例子后面都有完整的测试代码,你可以随时重复测试。
简介
我想把大约100个视图嵌套在一起进行比较,但我遇到了一个xml解析错误。AAPT: error: failed to parse proto XML 这个错误发生在嵌套超过49个视图的时候。因此,在下面的比较中,我正好用这个数量的嵌套元素进行操作。为了直观地显示和控制正在发生的事情,我给每个元素分配了不同的背景颜色和一些缩进。正如你在左边的图片中所看到的,红色视图嵌套了一个覆盆子视图,深红色视图嵌套了一个紫色视图,等等。这一组例子将展示深度嵌套在不同的执行选项中对性能的影响:xml、代码、编译、混合(xml+编译)。这些例子将被标记为深度。
在此过程中,我创造了另一个关键案例--"非常宽的嵌套"。也就是说,我在一个视图中也放了49个元素,并用不同的颜色给它们着色(见右边的图片)。我特意没有使用RecyclerView和LazyColumn来进行比较。这组例子将被标记为宽度。每个视图也被涂上颜色,以控制发生什么。
我们现在的任务是弄清每一次执行时的渲染速度,并回答几个问题。
a) 当嵌套很深很宽时,使用compose会不会有优势?
b)在这些情况下,混合状态是否会影响渲染速度和性能?
我们将使用两点之间的片段进行测量。开始点是在**super.onCreate(savedInstanceState)之后。结束点是在super.onResume()之后。时间将用System.currentTimeMillis()**来测量,因为我们不需要计算绝对值,所以使用更精确的工具没有意义。
XML深度
让我们从第一个例子开始。让我们把49倍的FrameLayout放进对方,用标准的颜色给背景着色。让我们添加缩进。
...
XML宽度
让我们把下面这个例子放到LinearLayout49FrameLayout中。我特意没有使用RecyclerView来确定视图在没有优化的情况下宽嵌套的表现。
...
代码深度
在这个例子中,我们会把49FrameLayout放进去,但在运行时。我们也会用标准的颜色给它着色,并添加缩进。在这个例子中,我们事先知道xml会更快,因为没有xml解析的步骤。这个例子与compose非常接近。相反,这里的目标是找出多年来在View中积累了多少影响力的遗产。正如你将在下面看到的,遗留代码的影响是相当大的。
//49 times
FrameLayout(this)
FrameLayout(this)
FrameLayout(this)
...
代码宽度
在这个例子中,我们将把49个FrameLayout垂直地放在LinearLayout中。让我们为每个元素添加颜色。
LinearLayout(this)
//49 times
FrameLayout(this)
FrameLayout(this)
FrameLayout(this)
编排深度
在这个例子中,让我们最终开始使用compose。让我们像xml例子中那样,在Box49里面互相嵌套,实现深度嵌套。基于这两个结果,我们将能够比较深度嵌套是否会影响视图层次的渲染速度。
//49 times
Box()
Box()
Box()
...
构成宽度
在这个例子中,和xml的例子一样,我们将通过在一个Column中插入49个Boxes来做一个宽的嵌套。就像上面的例子一样,我们故意不使用LazyColumn。基于这个例子和上面xml中的例子,我们可以得出结论,宽嵌套是否会影响渲染的速度。
Column()
//49 times
Box()
Box()
Box()
...
混合(xml+compose)深度
在这个例子中,我们先放24个FrameLayout,然后放ComposeView。在ComposeView中,我们要放24个Box(24个FrameLayout+ 1个ComposeView+ 24个Box= 49)。这样我们就可以评估重构过程中的混合状态是否会影响视图的性能和渲染速度。让我们假设所有的FrameLayout是剩余的遗产,而Box是重构的部分。
...
//24 times
Box()
Box()
Box()
...
混合:xml+compose宽度
在这个例子中,在LinearLayout中创建49个ComposeViews,并在每一个中放一个Box。
Box()
Box()
Box()
...
总结
让我们用图表总结一下所有的结果。
结果是非常可预测的。Compose比xml快50%。Xml由于解析和视图代码中存在大量的遗留问题,所以比较慢。
为了回答原来的两个问题,我们得出结论。
a) 深嵌套和宽嵌套对视图渲染速度没有影响。
b) 混合状态**(xml+compose**)相对于原始xml来说不影响渲染速度,所以你可以重构而不用担心有副作用。
还有几个有趣的点。
a) 当使用xml时,当视图嵌套深度增加时,性能会下降,尽管只是轻微的下降。使用代码或compose,由于缺乏解析,嵌套深度和宽度没有影响。唯一的区别是更优化的视图构造和compose中没有遗留问题。从图中可以看出,遗留问题影响了大约20-30%。
l o a d i n g
. ..评论及更多!