Android 为什么 0dp 被认为是一种性能增强?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12016781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:29:56  来源:igfitidea点击:

Why is 0dp considered a performance enhancement?

androidandroid-layoutandroid-lint

提问by Kirk

An answerat the end of this question has been filled out, combining remarks and solutions.

已填写本题末尾的一个答案,结合评论和解决方案。

Question

I searched around but haven't found anything that really explains why Android Lintas well as some Eclipsehints suggest replacing some layout_heightand layout_widthvalues with 0dp.

我四处搜索,但没有找到任何能真正解释为什么Android Lint以及一些Eclipse提示建议将 somelayout_heightlayout_widthvalues替换为0dp.

For example, I have a ListViewthat was suggested to be changed

例如,我有一个ListView建议更改的

Before

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

After

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</ListView>

Similarly, it suggested changes to a ListView item. These all look the same before and after the changes, but I'm interested in understanding why these are performance boosters.

同样,它建议更改ListView item。这些在更改前后看起来都一样,但我有兴趣了解为什么这些是性能助推器。

Anyone have an explanation of why? If it helps, here is general layout with the ListView.

任何人都解释为什么?如果有帮助,这里是带有ListView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ImageView
        android:id="@+id/logo_splash"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ImageView>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:background="@color/background"
        android:layout_below="@id/logo_splash">

        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
        </ListView>

        <TextView
            android:id="@android:id/empty"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/no_upcoming" />

    </LinearLayout>        
</RelativeLayout>

Answer

回答

I'm putting in an answer here because it's really a combination of answers and referenced links below. If I'm wrong on something, do let me know.

我在这里输入答案是因为它实际上是答案和下面参考链接的组合。如果我做错了什么,请告诉我。

From What is the trick with 0dip layout_height or layouth_width?

0dip layout_height 或 layouth_width 的技巧是什么?

There are 3 general layout attributes that work with widthand height

有 3 个通用布局属性适用于宽度高度

  1. android:layout_height
  2. android:layout_width
  3. android:layout_weight
  1. android:layout_height
  2. android:layout_width
  3. android:layout_weight

When a LinearLayoutis vertical, then the layout_weightwill effect the heightof the child Views (ListView). Setting the layout_heightto 0dpwill cause this attribute to be ignored.

当 aLinearLayoutvertical 时layout_weight将影响孩子s ( )的高度。将 设置为将导致此属性被忽略。ViewListViewlayout_height0dp

Example

例子

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </ListView>
</LinearLayout>

When a LinearLayoutis horizontal, then the layout_weightwill effect the widthof the child Views (ListView). Setting the layout_widthto 0dpwill cause this attribute to be ignored.

当 aLinearLayout水平时layout_weight将影响子s ( )的宽度。将 设置为将导致此属性被忽略。ViewListViewlayout_width0dp

Example

例子

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <ListView
        android:id="@android:id/list"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </ListView>
</LinearLayout>

The reason to want to ignore the attribute is that if you didn't ignore it, it would be used to calculate the layout which uses more CPU time.

要忽略该属性的原因是,如果您没有忽略它,它将用于计算占用更多 CPU 时间的布局。

Additionally this prevents any confusion over what the layout should look like when using a combination of the three attributes. This is highlighted by @android developerin an answer below.

此外,这可以防止在使用三个属性的组合时对布局的外观产生任何混淆。@android 开发人员在下面的回答中强调了这一点。

Also, Android Lintand Eclipseboth say to use 0dip. From that answer below, you can use 0dip, 0dp, 0px, etc since a zero size is the same in any of the units.

此外,Android LintEclipse都说要使用0dip. 从下面的答案中,您可以使用0dip0dp0px等,因为任何单位中的零大小都相同。

Avoid wrap_content on ListView

避免在 ListView 上使用 wrap_content

From Layout_width of a ListView

来自ListView 的 Layout_width

If you've ever wondered why getView(...)is called so many times like I have, it turns out to be related to wrap_content.

如果你曾经想知道为什么getView(...)像我一样被调用这么多次,结果证明它与wrap_content.

Using wrap_contentlike I was using above will cause all child Views to be measured which will cause further CPU time. This measurement will cause your getView(...)to be called. I've now tested this and the number of times getView(...)is called is reduced dramatically.

wrap_content像我上面使用的那样使用将导致所有 childView被测量,这将导致更多的 CPU 时间。此测量将导致您getView(...)被调用。我现在已经对此进行了测试,并且getView(...)被调用的次数大大减少了。

When I was using wrap_contenton two ListViews, getView(...)was called 3 times for each row on one ListViewand 4 times for each row on the other.

当我wrap_content在两个ListViews上使用时getView(...),每行被调用 3 次,另一行被调用ListView4 次。

Changing this to the recommended 0dp, getView(...)was called only once for each row. This is quite an improvement, but has more to do with avoiding wrap_contenton a ListViewthan it does the 0dp.

将此更改为推荐的0dp,getView(...)每行仅调用一次。这是一个相当大的改进,但更多地是避免wrap_content在 a 上而ListView不是在0dp.

However the suggestion of 0dpdoes substantially improve performance because of this.

然而,0dp由于这个原因,的建议确实大大提高了性能。

采纳答案by Lalit Poptani

First of all you have this,

首先你有这个

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

Never take the ListView's height as wrap_content, that will lead into troubles. Hereis the reason for that and this answer.

千万不要把ListView的高度当成wrap_content,那样会带来麻烦。Here是原因 和this answer

Further more,

此外,

I searched around but haven't found anything that really explains why Android Lint as well as some Eclipse hints suggests replacing some layout_height and layout_width values with 0dp.

我四处搜索,但没有找到任何能真正解释为什么 Android Lint 以及一些 Eclipse 提示建议将一些 layout_height 和 layout_width 值替换为 0dp 的内容。

Its because you are using layout_weight = "1"that means your ListView with take the height as much as is available to it. So, in that case there is no need of using layout_height = "wrap_content"just change it to android:layout_height="0dp"and ListView's height will be managed by layout_weight = "1".

这是因为您正在使用layout_weight = "1"这意味着您的 ListView 尽可能多地使用它可用的高度。因此,在这种情况下,无需使用,layout_height = "wrap_content"只需将其更改为android:layout_height="0dp",ListView 的高度将由layout_weight = "1".

回答by Archie.bpgc

So when android:layout_weight is used on View X and LinearLayout is horizontal, then X's android:layout_width is simply ignored.

所以当 android:layout_weight 用于 View X 并且 LinearLayout 是水平的时,那么 X 的 android:layout_width 会被忽略。

Similar, when android:layout_weight is used on View X and LinearLayout is vertical, then X's android:layout_height is ignored.

类似的,当 android:layout_weight 用于 View X 且 LinearLayout 为垂直时,则忽略 X 的 android:layout_height。

This actually means, that you can put anything in those ignored fields: 0dp or fill_parent or wrap_content. It doesn't matter. But it's recommended to use 0dp so View's do not do extra calculation of their height or width (which is then ignored). This small trick simply saves CPU cycles.

这实际上意味着,您可以在这些被忽略的字段中放入任何内容:0dp 或 fill_parent 或 wrap_content。没关系。但建议使用 0dp,这样 View 就不会额外计算它们的高度或宽度(然后被忽略)。这个小技巧只是节省了 CPU 周期。

from :

从 :

What is the trick with 0dip layout_height or layouth_width?

0dip layout_height 或 layouth_width 有什么技巧?

回答by android developer

as far as i know , there is a difference between using 0dp (or 0px btw, it's the same since 0 is 0 no matter what is the unit here ) and the wrap_content or fill_parent (or match_parent, it's the same).

据我所知,使用 0dp(或 0px 顺便说一句,它是相同的,因为 0 是 0,无论这里的单位是什么)和 wrap_content 或 fill_parent(或 match_parent,它是相同的)。

it depends on the weight you use . if you only use weight of 1 , they all look the same , but the meaning is always different , and it is important for performance.

这取决于您使用的重量。如果只使用权重 1,它们看起来都一样,但含义总是不同的,这对性能很重要。

in order to show this , try the following:

为了显示这一点,请尝试以下操作:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
  android:layout_height="match_parent" android:orientation="vertical">

  <TextView android:id="@+id/textView1" android:layout_width="match_parent"
    android:layout_height="0px" android:text="1" android:background="#ffff0000"
    android:layout_weight="1" android:gravity="center"
    android:textColor="#ffffffff" android:textSize="20sp" />

  <TextView android:id="@+id/textView2" android:layout_width="match_parent"
    android:layout_height="0px" android:text="2" android:background="#ff00ff00"
    android:layout_weight="2" android:gravity="center"
    android:textColor="#ffffffff" android:textSize="20sp" />

  <TextView android:id="@+id/textView3" android:layout_width="match_parent"
    android:layout_height="0px" android:text="3" android:background="#ff0000ff"
    android:layout_weight="3" android:gravity="center"
    android:textColor="#ffffffff" android:textSize="20sp" />

</LinearLayout>

and then try to replace the 0px with match_parent . you will see that the result is very different.

然后尝试用 match_parent 替换 0px 。你会看到结果是非常不同的。

usually , for both better understanding and for better performance , you would want to use 0px.

通常,为了更好的理解和更好的性能,你会想要使用 0px。

回答by Karu

LinearLayoutmeasures all the children according to the layout_width/layout_heightvalues, then divides up the leftover space (which may be negative) according to the layout_weightvalues.

LinearLayout根据layout_width/layout_height值测量所有孩子,然后根据值划分剩余空间(可能为负)layout_weight

0dpis more efficient than wrap_contentin this case because it's more efficient to just use zero for the original height and then split the parent's full height based on the weight than to measure the child first and then split the remainder based on the weight.

0dpwrap_content在这种情况下更有效,因为只对原始高度使用零,然后根据体重分割父母的全高比先测量孩子然后根据体重分割其余部分更有效。

So the efficiency comes from not measuring the child. 0dpshould be exactly as efficient (and produce exactly the same result) as match_parent, or 42px, or any other fixed number.

所以效率来自不测量孩子。0dp应该与match_parent、 或42px或任何其他固定数字完全一样有效(并产生完全相同的结果)。

回答by Damien

Caution re using android:layout_height="0dp"

注意重新使用 android:layout_height="0dp"

I have found that in a ListView (with the recommended View recycling using convertView, see e.g. http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/), setting android:layout_height="0dp" for the row TextView can lead to text truncation for multi-line text content.

我发现在 ListView 中(使用convertView 推荐的View 回收,参见例如http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/),设置android:layout_height=" 0dp" 行 TextView 可能导致多行文本内容的文本截断。

Whenever a TextView object that was previously used to display a text that fitted in a single line is recycled to display a longer text that needs more than one line, that text is truncated to a single line.

每当以前用于显示适合单行的文本的 TextView 对象被回收以显示需要多于一行的较长文本时,该文本将被截断为单行。

The problem is cured by using android:layout_height="wrap_content"

问题通过使用 android:layout_height="wrap_content" 解决