Android布局测量时间随着层次结构的每一步增加一倍

rsl1atfo  于 2023-01-19  发布在  Android
关注(0)|答案(2)|浏览(152)

我在hierarchyviewer中分析平板电脑用户界面,注意到measuretimes(从树的底部开始向上移动)中存在以下模式:
~40毫秒~80毫秒~160毫秒~320毫秒~640毫秒~1280毫秒
我假设问题是带有嵌套权重的LinearLayouts,所以我删除了整个层次结构中的所有LinearLayouts和权重。
~40毫秒~80毫秒~160毫秒~160毫秒~160毫秒~160毫秒~310毫秒
更好,但每隔几级它仍然会翻倍。是什么原因导致的?
下面是此路径的完整层次结构(请原谅长度......请随意向我提供您最好的优化技巧):

[generated layouts]
 *RelativeLayout [309 ms]
   FrameLayout [164 ms]
    NoSaveStateFrameLayout [160 ms]
    *RelativeLayout [151 ms]
     *RelativeLayout [77 ms]
       ListView [45 ms]
        GridLayout [46 ms]
         Spinner [4.4 ms]
          TextView [0.1 ms]
  • 查看时间加倍

任何建议将不胜感激!提前感谢。

TL; DR

  • 除嵌套权重外,还有什么因素会导致测量时间呈指数增长?*
6kkfgxo0

6kkfgxo01#

Simon之前的回答并不完全正确,确实有一个测量通道和一个布局通道,但这一事实本身并不会导致指数放大。
如果您在层次结构中的各个视图上的onMeasure()和onLayout()中放置轨迹,您会发现布局通道不是问题:onLayout()在每个View上只被调用一次,这使得它成为一个线性时间遍历。度量传递是个问题--对于ViewGroup的 * 一些 * 子类,使用 * 一些 * 参数,onMeasure()最终调用每个子类的onMeasure()两次,这当然会导致您所看到的行为。
RelativeLayout是这些“坏公民”中的一个,它对每个孩子测量两次,同意你的观察。
另一个不好的例子是LinearLayout,当子节点具有MATCH_PARENT和非零权重时,我已经看过它的实现,我大致了解了它的工作原理--首先,它递归地测量子节点一次,看看它们希望有多大,然后,如果有任何松弛(或收缩),它会再次测量具有非零权重的子节点,以便分配松弛。
请注意,RelativeLayout经常被引用作为指数爆炸的解决方案,尽管它是导致爆炸的坏公民之一。我相信原因是RelativeLayout具有足够的表达能力,可以将LinearLayouts的深层次结构重新表达为单个RelativeLayout。这一点非常重要--如果您简单地用RelativeLayouts替换LinearLayouts而不将层次结构扁平化,你仍然会得到指数测度时间。
我还不清楚指数级的爆炸是否可以最终在核心库中被简单地优化掉(也许通过将现有的测量通道分成优选尺寸聚集通道和分配松弛通道,其中每一个都可以在线性时间内完成并且不需要彼此调用)或者在LinearLayout和RelativeLayout的契约中是否存在某些东西使得递归双精度-测量儿童的内在必要性。

ctehm74n

ctehm74n2#

Android在2个通道中构建布局。
第一个环节是测量环节,所有的孩子都被问到他们想要多大,然后是布局环节,父母告诉孩子他们有多大,并要求他们画出来。
因此,添加一个额外的ViewGroup级别大约会使时间加倍,这与您给出的示例一致。

相关问题