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

Android布局测量时间随着层次结构的每一步而加倍,android,android-layout,hierarchyviewer,Android,Android Layout,Hierarchyviewer,我在hierarchyviewer中分析一个tablet UI,我注意到在测量时间内(从树的底部开始向上移动)出现了以下模式: ~40毫秒~80毫秒~160毫秒~320毫秒~640毫秒~1280毫秒 我假设问题是带有嵌套权重的LinearLayouts,所以我删除了整个层次结构中的所有LinearLayouts和权重。现在我有这个: ~40毫秒~80毫秒~160毫秒~160毫秒~160毫秒~310毫秒 更好,但它仍然每几级翻一番这是什么原因造成的? 以下是此路径的完整层次结构(请原谅长度…请随意

我在hierarchyviewer中分析一个tablet UI,我注意到在测量时间内(从树的底部开始向上移动)出现了以下模式:

~40毫秒~80毫秒~160毫秒~320毫秒~640毫秒~1280毫秒

我假设问题是带有嵌套权重的LinearLayouts,所以我删除了整个层次结构中的所有LinearLayouts和权重。现在我有这个:

~40毫秒~80毫秒~160毫秒~160毫秒~160毫秒~310毫秒

更好,但它仍然每几级翻一番这是什么原因造成的?

以下是此路径的完整层次结构(请原谅长度…请随意向我介绍您的最佳优化技巧):

*查看时间加倍

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

TL;博士
除了嵌套权重,是什么导致测量时间呈指数级增长?

Android在两次过程中构建布局

第一个是测量通过,当所有的孩子都被问到他们想要多大。然后,当家长告诉孩子们他们有多大,并要求他们画画时,会进行布局传递


因此,添加额外的视图组级别会使时间大致增加一倍。这与您给出的示例是一致的。

Android在两次过程中构建布局

第一个是测量通过,当所有的孩子都被问到他们想要多大。然后,当家长告诉孩子们他们有多大,并要求他们画画时,会进行布局传递


因此,添加额外的视图组级别会使时间大致增加一倍。这与你给出的例子是一致的。

西蒙之前的回答不太正确。 是的,有一个测量过程和一个布局过程, 但这一事实本身并不会导致指数级爆炸

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

RelativeLayout是这些“坏公民”中的一员,会对每个孩子进行两次测量, 同意你的观察

另一个坏公民(如你所知) 当子项具有匹配父项和非零权重时,为线性布局。 我已经看过了实现,大致了解了它的功能-- 首先,它递归地测量孩子们一次,看看他们想要多大, 然后,如果有任何松弛(或收缩), 它再次测量非零体重的儿童 为了分配空闲时间

请注意,RelativeLayout经常被引用为 指数级的爆炸,尽管它是造成爆炸的坏公民之一。 我相信原因是相对论是有表现力的 足够使线性布局的深层层次结构可以重新表示为单个RelativeLayout。 这是非常重要的一点——如果您只是简单地替换线性布局 使用RelativeLayouts而不扁平化层次结构,您仍将具有指数 测量时间

我不清楚指数爆炸是否是 最终可以在核心库中进行简单的优化 (可能通过将现有度量过程分离为聚集首选大小过程 和一个分布式松弛过程,每个过程都可以在线性时间内完成 (不需要互相打电话) 或者在LinearLayout的 和RelativeLayout的契约,使
对儿童进行双重测量是必然的。

西蒙之前的回答不太正确。 是的,有一个测量过程和一个布局过程, 但这一事实本身并不会导致指数级爆炸

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

RelativeLayout是这些“坏公民”中的一员,会对每个孩子进行两次测量, 同意你的观察

另一个坏公民(如你所知) 当子项具有匹配父项和非零权重时,为线性布局。 我已经看过了实现,大致了解了它的功能-- 首先,它递归地测量孩子们一次,看看他们想要多大, 然后,如果有任何松弛(或收缩), 它再次测量非零体重的儿童 为了分配空闲时间

请注意,RelativeLayout经常被引用为 指数级的爆炸,尽管它是造成爆炸的坏公民之一。 我相信原因是相对论是有表现力的 足够使线性布局的深层层次结构可以重新表示为单个RelativeLayout。 这是非常重要的一点——如果您只是简单地替换线性布局 使用RelativeLayouts而不扁平化层次结构,您仍将具有指数 测量时间

我不清楚指数爆炸是否是 最终可以在核心库中进行简单的优化 (可能通过将现有度量过程分离为聚集首选大小过程 和一个分布式松弛过程,每个过程都可以在线性时间内完成 (不需要互相打电话) 或者在LinearLayout的 和RelativeLayout的契约,使
对儿童进行双重测量是必要的。

谢谢您的回答!这带来了一个不同的问题:为什么(在我的第二个示例中)在某些布局上测量时间只加倍?而且,这只能解决吗
[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]