Почему 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 общих атрибута макета, которые работают с шириной и высотой
android:layout_height
android:layout_width
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
Если вы когда-нибудь задумывались, почему getView(...)
называется так много раз, как у меня, оказывается, связано с wrap_content
,
С помощью wrap_content
как я использовал выше, будет причиной всех детей View
s будет измеряться, что приведет к увеличению времени процессора. Это измерение приведет к вашему getView(...)
быть названным. Я сейчас проверил это и количество раз getView(...)
называется резко сокращено.
Когда я использовал wrap_content
на двух ListView
s, 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 не делали дополнительного расчета их высоты или ширины (что затем игнорируется). Этот маленький трюк просто экономит циклы процессора.
от:
Насколько я знаю, есть разница между использованием 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"