Чому 0dp вважається підвищенням продуктивності?


75

Відповідь в кінці цього питання був заповнений, комбінуючи зауваження і рішення.

Питання

Я шукав навколо, але не знайшов нічого, що справді пояснює, чому 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_heightTo 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_widthTo 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як я використовував вище, призведе Viewдо вимірювання всіх дочірніх елементів, що призведе до подальшого часу процесора. Це вимірювання призведе getView(...)до того, що вас покличуть. Зараз я це перевірив, і кількість getView(...)викликів різко зменшується.

Коли я використовував wrap_contentпо два ListViewс, мене getView(...)викликали 3 рази для кожного рядка по одному ListViewі 4 рази для кожного рядка з іншого.

Змінивши це на рекомендоване 0dp, getView(...)викликався лише один раз для кожного рядка. Це досить поліпшення, але має більше спільного з уникаючи wrap_contentна ListViewніж це робить 0dp.

Однак пропозиція 0dpсуттєво покращує продуктивність через це.



1
Приємна знахідка, я її не знайшов. Відповідь, яка не була прийнята, є тією, яка пояснює це
Кірк

Мене змусило побачити, що питання має більше голосів, ніж відповідь, але тепер я розумію, чому. Дивовижні запитання. Якщо ви бажаєте, це створило б чудову вікі-спільноту. Дякую за це!
RileyE

Відповіді:


24

Перш за все у вас є це,

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


12

Отже, коли android: layout_weight використовується у View X, а LinearLayout горизонтальний, тоді android: layout_width просто ігнорується.

Подібно, коли android: layout_weight використовується у View X, а LinearLayout вертикальний, тоді android: layout_height X ігнорується.

Це насправді означає, що ви можете помістити що завгодно в ці ігноровані поля: 0dp або fill_parent або wrap_content. Це не має значення. Але рекомендується використовувати 0dp, тому View не роблять додаткового обчислення своєї висоти або ширини (що потім ігнорується). Цей невеликий прийом просто економить цикли процесора.

від:

У чому фокус з 0dip layout_height або layouth_width?


5

наскільки я знаю, існує різниця між використанням 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.


3

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

0dpє ефективнішим, ніж wrap_contentу цьому випадку, оскільки ефективніше просто використовувати нуль для початкової висоти, а потім розділити повний зріст батьків на основі ваги, ніж спочатку виміряти дитину, а потім розділити решту на основі ваги.

Отже, ефективність полягає в тому, що не вимірювати дитину. 0dpмає бути точно таким же ефективним (і давати точно такий же результат), як match_parent, або 42px, або будь-яке інше фіксоване число.


1

Обережно при використанні 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"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.