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

时间:2012-12-12 23:32:20

标签: android android-layout hierarchyviewer

我正在分析层次结构视图中的平板电脑用户界面,我注意到度量次的以下模式(从树的基础开始向上移动):

... ~40 ms ... ~80 ms ... ~160 ms ... ~320 ms ... ~640 ms ... ~1280 ms ......

我认为问题是具有嵌套权重的LinearLayouts,因此我删除了整个层次结构中的所有LinearLayouts和权重。现在我有了这个:

... ~40 ms ... ~80 ms ... ~160 ms ... ~160 ms ... ~160 ms ... ~310 ms ......

更好,但它仍然每隔几个级别加倍。 可能导致这种情况的原因是什么?

以下是此路径的完整层次结构(请原谅长度......随意向我提出最佳优化提示):

[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

除嵌套权重外,是什么导致测量时间呈指数增长?

2 个答案:

答案 0 :(得分:4)

西蒙以前的回答并不完全正确。 确实有一个度量传递和布局传递, 但这一事实本身并没有导致指数爆炸。

如果在onMeasure()和onLayout()中放置了层次结构中各种视图的跟踪, 你会发现布局传递不是问题:onLayout() 只在每个View上调用一次,使其成为线性时间遍历。 度量传递是问题 - 对于 ViewGroup的一些子类, 使用一些参数,onMeasure()最终会调用每个孩子的onMeasure()两次, 这当然会导致你所看到的行为。

RelativeLayout是衡量每个孩子两次的“坏公民”之一, 同意你的观察。

另一个坏公民(如你所知) 当孩子有MATCH_PARENT和非零权重时,是LinearLayout。 我看了一下实现,我大致跟着它做了什么 - 首先它递归地测量孩子一次,看看他们想要多大, 那么,如果有任何松弛(或收缩), 它再次测量非零体重的孩子 为了分配松弛。

请注意,RelativeLayout经常被引用作为解决方案 指数爆炸,即使它是造成它的坏公民之一。 我相信其原因是RelativeLayout具有表现力 可以将LinearLayouts的深层次结构重新表达为单个RelativeLayout。 这是非常重要的一点 - 如果您只是替换LinearLayouts 如果没有展平层次结构的RelativeLayouts,你仍然会有指数 测量时间。

我不清楚指数爆炸是否是那样的 最终可以简单地在核心库中进行优化 (也许通过将现有的度量传递分离为聚集首选大小传递 和分布松弛的通行证,每个通行证都可以在线性时间内完成 而且不需要互相打电话) 或者LinearLayout中是否有东西 和RelativeLayout的合同,使递归 儿童的双重测量本身就是必要的。

答案 1 :(得分:0)

Android在2遍中构建布局。

第一个是测量通过,当所有孩子被问到他们想要多大时。然后布局传递,当父母告诉孩子他们有多大并请求他们画画时。

因此,添加额外的ViewGroup级别大致会使时间翻倍。这与您给出的示例一致。