嵌套带有权重的线性布局,为什么被认为是不好的?
Nesting Linear Layouts with Weights, Why Considered Bad?
所以,我从 2011 年 2 月左右开始在 Android 上进行开发。我一直敏锐地意识到的一件事是,具有权重和权重总和的嵌套线性布局是 'bad for performance' 并且编译器(至少 eclipse 做到了)在你 dd 时发出警告。
但是,根据我的经验,这样做对用户体验或切换屏幕的速度没有明显影响。作为一项实验,我创建了以下屏幕,该屏幕除了一个巨型 O.T.T 外,没有其他任何特征。使用权重和嵌套线性布局。我使用了对比色来显示所有使用的线性布局。好处是大屏幕和小屏幕看起来一样。
我已经在 Galaxy S4、Galaxy Note 10.0、Galaxy note 3 7" 和非常小的低功率 Galaxy Neo 上试过了。我已经在 Gingerbread、Cream Sandwich、Kitkat 和 Lollupop 上试过了,但没有查看此屏幕与相对布局上具有 4 个按钮的简单屏幕之间任何可察觉的速度差异。
那么,是什么让这个主意如此糟糕?幕后发生了什么使这不是一个理想的解决方案?当我将可绘制对象或图像添加到混合中时,所有这一切都会改变吗?
So what makes this such a bad idea?
这主意不错。它也不是免费的。
特别是,尽管您提出相反的抗议,但您的情况相当简单。虽然您的布局相当复杂,但它只渲染一次。因此,虽然您可能会在渲染时丢掉几帧,但这个代价是一次性支付的(或者更准确地说,使用此布局的每个 activity/fragment 支付一次)。
当每个布局费用变得更大的问题是,当它被其中的几个动画放大时,例如 ListView
/RecyclerView
中的行或 RecyclerView
中的页面一个ViewPager
。现在,我们正在经历 很多很多 渲染通道,因为用户滑动并导致我们重新绘制我们的内容。列表中的每一行可能比您的布局要简单得多,但我们也将尝试每秒绘制多次。而且,虽然在您的情况下可能不会注意到几个丢帧,但动画期间的丢帧几乎是 Android UI.
的 "jank" 的定义
只要你没有卡顿——IOW,你就不会丢掉任何帧,如 LogCat 中的 Choreographer
所报告或通过 Developer 在 gfxinfo
覆盖图中看到的那样选项——那么您的布局很好,至少就我和可能大多数用户而言是这样。相反,如果您 正在 丢帧,尝试找出更有效的布局,甚至可能是自定义布局 ViewGroups
而不是通用布局,可能有助于缓解这种卡顿现象。
这里的主要问题与如何 Android positions your views on screen 有关。任何时候相对于视图的位置发生变化,然后 "layout" 通过视图层次结构级联,接触每个视图并执行一些计算(类似于更改 "sizes" 启动 "measure"通过)。
一些布局容器,如 RelativeLayout,必须强制第 2 次 "layout" pass 才能开始;一旦所有视图都计算出它们所需的位置,ReltativeLayout 需要根据其布局属性再次重新定位所有内容。
这会导致 Double Layout Taxation 通过视图层次结构;这不是免费的。
现在,如果您有一个 浅层 层次结构,此操作的开销是微不足道的。这开始 运行 成为问题的地方是当你有一个很深的层次结构时,其中有多个双布局容器。例如,在根部有一个 RelativeLayout,其中包含设置了 "measure with largest child" 的 LinearLayout。结果是叶节点视图将被 "layout" 调用约 8 次。
这对性能的影响与场景中 layout/measure 通道的复杂程度直接相关。如果没有问题,也许 12x-per-view 布局通道在高端设备上不是什么大问题。但是,如果其中一个叶节点具有复杂的布局通道,那么,您只是在浪费周期。
此处的主要主题是分析有问题的事物,但请记住,以错误的方式设置事物只会浪费本可用于其他地方的性能。
所以,我从 2011 年 2 月左右开始在 Android 上进行开发。我一直敏锐地意识到的一件事是,具有权重和权重总和的嵌套线性布局是 'bad for performance' 并且编译器(至少 eclipse 做到了)在你 dd 时发出警告。
但是,根据我的经验,这样做对用户体验或切换屏幕的速度没有明显影响。作为一项实验,我创建了以下屏幕,该屏幕除了一个巨型 O.T.T 外,没有其他任何特征。使用权重和嵌套线性布局。我使用了对比色来显示所有使用的线性布局。好处是大屏幕和小屏幕看起来一样。
我已经在 Galaxy S4、Galaxy Note 10.0、Galaxy note 3 7" 和非常小的低功率 Galaxy Neo 上试过了。我已经在 Gingerbread、Cream Sandwich、Kitkat 和 Lollupop 上试过了,但没有查看此屏幕与相对布局上具有 4 个按钮的简单屏幕之间任何可察觉的速度差异。
那么,是什么让这个主意如此糟糕?幕后发生了什么使这不是一个理想的解决方案?当我将可绘制对象或图像添加到混合中时,所有这一切都会改变吗?
So what makes this such a bad idea?
这主意不错。它也不是免费的。
特别是,尽管您提出相反的抗议,但您的情况相当简单。虽然您的布局相当复杂,但它只渲染一次。因此,虽然您可能会在渲染时丢掉几帧,但这个代价是一次性支付的(或者更准确地说,使用此布局的每个 activity/fragment 支付一次)。
当每个布局费用变得更大的问题是,当它被其中的几个动画放大时,例如 ListView
/RecyclerView
中的行或 RecyclerView
中的页面一个ViewPager
。现在,我们正在经历 很多很多 渲染通道,因为用户滑动并导致我们重新绘制我们的内容。列表中的每一行可能比您的布局要简单得多,但我们也将尝试每秒绘制多次。而且,虽然在您的情况下可能不会注意到几个丢帧,但动画期间的丢帧几乎是 Android UI.
只要你没有卡顿——IOW,你就不会丢掉任何帧,如 LogCat 中的 Choreographer
所报告或通过 Developer 在 gfxinfo
覆盖图中看到的那样选项——那么您的布局很好,至少就我和可能大多数用户而言是这样。相反,如果您 正在 丢帧,尝试找出更有效的布局,甚至可能是自定义布局 ViewGroups
而不是通用布局,可能有助于缓解这种卡顿现象。
这里的主要问题与如何 Android positions your views on screen 有关。任何时候相对于视图的位置发生变化,然后 "layout" 通过视图层次结构级联,接触每个视图并执行一些计算(类似于更改 "sizes" 启动 "measure"通过)。
一些布局容器,如 RelativeLayout,必须强制第 2 次 "layout" pass 才能开始;一旦所有视图都计算出它们所需的位置,ReltativeLayout 需要根据其布局属性再次重新定位所有内容。
这会导致 Double Layout Taxation 通过视图层次结构;这不是免费的。
现在,如果您有一个 浅层 层次结构,此操作的开销是微不足道的。这开始 运行 成为问题的地方是当你有一个很深的层次结构时,其中有多个双布局容器。例如,在根部有一个 RelativeLayout,其中包含设置了 "measure with largest child" 的 LinearLayout。结果是叶节点视图将被 "layout" 调用约 8 次。
这对性能的影响与场景中 layout/measure 通道的复杂程度直接相关。如果没有问题,也许 12x-per-view 布局通道在高端设备上不是什么大问题。但是,如果其中一个叶节点具有复杂的布局通道,那么,您只是在浪费周期。
此处的主要主题是分析有问题的事物,但请记住,以错误的方式设置事物只会浪费本可用于其他地方的性能。