我正在分析层次结构视图中的平板电脑用户界面,我注意到度量次的以下模式(从树的基础开始向上移动):
... ~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]
*查看时间加倍
任何建议将不胜感激!提前谢谢。
除嵌套权重外,是什么导致测量时间呈指数增长?
答案 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级别大致会使时间翻倍。这与您给出的示例一致。