Почему 0dp считается повышением производительности?

В конце этого вопроса был дан ответ, сочетающий замечания и решения.

Вопрос

Я искал вокруг, но не нашел ничего, что действительно объясняет, почему Android Lint, а также некоторые подсказки Eclipse предлагают заменить некоторые layout_height а также layout_width значения с 0dp,

Например, у меня есть ListView это было предложено изменить

До

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

После

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

Точно так же это предложило изменения к элементу 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>

Ответ

Я добавляю ответ здесь, потому что это действительно комбинация ответов и ссылочных ссылок ниже. Если я ошибаюсь, дайте мне знать.

Из чего состоит хитрость с 0dip layout_height или layouth_width?

Существует 3 общих атрибута макета, которые работают с шириной и высотой

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

Когда LinearLayout вертикально, то layout_weight повлияет на рост ребенка Viewс (ListView). Настройка layout_height в 0dp приведет к игнорированию этого атрибута.

пример

<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>

Когда LinearLayout горизонтально, то layout_weight будет влиять на ширину ребенка Viewс (ListView). Настройка layout_width в 0dp приведет к игнорированию этого атрибута.

пример

<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>

Причина, по которой вы хотите игнорировать атрибут, заключается в том, что если вы его не игнорируете, он будет использоваться для расчета макета, который использует больше процессорного времени.

Кроме того, это позволяет избежать путаницы в том, как должен выглядеть макет при использовании комбинации трех атрибутов. Это подчеркнуто разработчиком @android в ответе ниже.

Кроме того, Android Lint и Eclipse оба говорят использовать 0dip, Из этого ответа ниже, вы можете использовать 0dip, 0dp, 0pxи т. д., поскольку нулевой размер одинаков в любом из блоков.

Избегайте wrap_content в ListView

Из Layout_width ListView

Если вы когда-нибудь задумывались, почему getView(...) называется так много раз, как у меня, оказывается, связано с wrap_content,

С помощью wrap_content как я использовал выше, будет причиной всех детей Views будет измеряться, что приведет к увеличению времени процессора. Это измерение приведет к вашему getView(...) быть названным. Я сейчас проверил это и количество раз getView(...) называется резко сокращено.

Когда я использовал wrap_content на двух ListViews, getView(...) был вызван 3 раза для каждого ряда по одному ListView и 4 раза для каждого ряда на другом.

Меняя это на рекомендуемое 0dp, getView(...) был вызван только один раз для каждого ряда. Это значительное улучшение, но больше связано с тем, чтобы избежать wrap_content на ListView чем это делает 0dp,

Однако предложение 0dp существенно улучшает производительность из-за этого.

5 ответов

Решение

Прежде всего, у вас есть это,

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

Никогда не воспринимайте высоту ListView как wrap_content, это приведет к неприятностям. Here является причиной этого и this answer,

Дальше больше,

Я искал вокруг, но не нашел ничего, что действительно объясняет, почему Android Lint, а также некоторые подсказки Eclipse предлагают заменить некоторые значения layout_height и layout_width на 0dp.

Это потому, что вы используете layout_weight = "1" это означает, что ваш ListView принимает высоту столько, сколько доступно для него. Таким образом, в этом случае нет необходимости использовать layout_height = "wrap_content" просто измените его на android:layout_height="0dp" и высота ListView будет управляться layout_weight = "1",

Поэтому, когда для View X используется android:layout_weight, а LinearLayout расположен горизонтально, android:layout_width X просто игнорируется.

Аналогично, когда android:layout_weight используется в View X и LinearLayout вертикальный, тогда android:layout_height X игнорируется.

На самом деле это означает, что вы можете поместить что-нибудь в эти игнорируемые поля: 0dp или fill_parent или wrap_content. Это не важно Но рекомендуется использовать 0dp, чтобы View не делали дополнительного расчета их высоты или ширины (что затем игнорируется). Этот маленький трюк просто экономит циклы процессора.

от:

Что за хитрость в 0dip layout_height или layouth_width?

Насколько я знаю, есть разница между использованием 0dp (или 0px, кстати, это то же самое, поскольку 0 равно 0 независимо от того, какая здесь единица измерения) и wrap_content или fill_parent (или match_parent, это одно и то же).

это зависит от веса, который вы используете. если вы используете только вес 1, все они выглядят одинаково, но значение всегда различно, и это важно для производительности.

чтобы показать это, попробуйте следующее:

<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>

а затем попробуйте заменить 0px на match_parent . вы увидите, что результат очень отличается.

обычно для лучшего понимания и повышения производительности вы можете использовать 0px.

LinearLayout измеряет всех детей в соответствии с layout_width/layout_height значения, а затем делит оставшееся пространство (которое может быть отрицательным) в соответствии с layout_weight ценности.

0dp более эффективен, чем wrap_content в этом случае, поскольку более эффективно просто использовать ноль для исходного роста, а затем разделить полный рост родителя на основе веса, чем сначала измерить ребенка, а затем разделить остаток на основе веса.

Таким образом, эффективность заключается в том, чтобы не измерять ребенка. 0dp должен быть точно таким же эффективным (и производить точно такой же результат), как match_parent, или же 42pxили любой другой фиксированный номер.

Осторожно при использовании Android:layout_height="0dp"

Я обнаружил, что в ListView (с рекомендуемой переработкой View с использованием convertView, см., Например, http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/), настройку android:layout_height="0dp"для строки TextView может привести к усечению текста для многострочного текстового содержимого.

Всякий раз, когда объект TextView, который ранее использовался для отображения текста, помещенного в одну строку, повторно используется для отображения более длинного текста, требующего более одной строки, этот текст усекается до одной строки.

Проблема устранена с помощью Android:layout_height="wrap_content"

Другие вопросы по тегам