Почему вложенные веса плохо влияют на производительность? Альтернативы?

160

Я написал пару файлов макетов, где я использовал layout_weightатрибут, чтобы создать соотношение между различными видами.

В какой-то момент я начинаю получать предупреждения о вложенных весах.

Итак, мне интересно, почему вложенные веса плохо влияют на производительность, и существует ли более эффективный способ создания постоянного соотношения между размерами представления, который можно использовать для экранов разных размеров и при этом не нужно указывать большое количество значений dpi измерения Через несколько файлов макетов (я имею в виду для разных размеров экрана).

Спасибо!

MobileCushion
источник
2
Отличный пост для оптимизации раскладки developer.android.com/training/improving-layouts/…
Мухаммад Бабар

Ответы:

140

Вложенные веса плохо влияют на производительность, потому что:

Веса макета требуют, чтобы виджет был измерен дважды. Когда LinearLayout с ненулевыми весами вложен в другой LinearLayout с ненулевыми весами, то количество измерений увеличивается в геометрической прогрессии.

Лучше использовать RelativeLayout s и настроить вид в соответствии с местами других видов без использования определенных значений dpi.

CD
источник
87
Хорошая вещь, о которой нужно знать, и я полагаю, что цель сообщения. Я хотел бы отметить, что экспоненциальное влияние все еще крошечно, если вовлеченный показатель мал. Для небольших глубин вложения не использовать процессор, необходимый для этого, все равно, что иметь рабочую лошадку, которую вы балуете всю неделю и выгуливаете только по воскресеньям. Тем не менее, для больших глубин вложения, это хорошо принятый момент.
Карл
14
RelativeLayout также нужно измерить дважды, чтобы убедиться, что все его дочерние макеты правильно, поэтому изменение LinearLayout с весом макета на RelativeLayout может не улучшить производительность.
Piasy
Относительное расположение не всегда работает. В случаях, когда нужно построить пропорциональные виджеты
Абдурахмон
67

Обновление: Как мы знаем, библиотека поддержки процентов устарела с уровня API 26. ConstraintLayoutЭто новый способ достижения такой же плоской XML-структуры.

Обновленный проект Github

Обновленные образцы:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/fifty_thirty"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff8800"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        android:textSize="25sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff5566"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        android:textSize="25sp"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintLeft_toRightOf="@id/fifty_thirty"
        app:layout_constraintTop_toBottomOf="@id/fifty_thirty"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

</android.support.constraint.ConstraintLayout>

Обновление: отличные новости android процент поддержки библиотека решает нашу проблему производительности и вложенного грязного взвешенногоLinearLayout

compile 'com.android.support:percent:23.0.0'

Демо ЗДЕСЬ

Рассмотрим этот простой макет, чтобы продемонстрировать то же самое.

процент поддержки libray demo

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/fifty_huntv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ff7acfff"
        android:text="20% - 50%"
        android:textColor="@android:color/white"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="50%" />
    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_toRightOf="@id/fifty_huntv"
        android:background="#ffff5566"
        android:text="80%-50%"
        app:layout_heightPercent="80%"
        app:layout_widthPercent="50%"
        />

</android.support.percent.PercentRelativeLayout>

Избегайте снижения производительности, вложенного LinearLayoutс весами. Действительно потрясающе !!!.

Nitesh
источник
@dan Да, учитывая, что у нас есть линейное расположение с весами.
Nitesh
3
«Этот класс устарел на уровне API 26.0.0-бета1. Рассмотрите возможность использования ConstraintLayout и связанных макетов». developer.android.com/reference/android/support/percent/...
saiyancoder
7
Мне не нравится ConstraintLayout. Это не ведет себя интуитивно для меня
Карсон
8
ConstraintLayout для меня так сложен
BertKing
1
Может быть, объяснения Apple, касающиеся ограничений автоматического размещения, более понятны, и, поскольку логика та же самая, это может помочь. К сожалению, я считаю, что ConstraintLayout дроида более тяжелый / многословный в использовании, чем AutoLayout для iOS
AdricoM
46

Я думаю (и я, вероятно, буду в восторге от этого), но снова я думаю, что мой телефон имеет четырехъядерный процессор, чтобы конкурировать (если не полностью уничтожить) большинство домашних компьютеров людей.

Я также думаю, что такого рода аппаратные возможности - будущее телефонов.

Поэтому я прихожу к выводу, что, пока вы не увлекаетесь вложением (в MHO макет никогда не должен иметь глубину более 4-х уровней, и если это так, то вы, вероятно, делаете это неправильно), ваш телефон может заботиться меньше о весах.

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

(обратите внимание, что я немного юмористичен, и поэтому не стоит воспринимать что-либо слишком серьезно из этого поста, кроме идеи о том, что сначала нужно оптимизировать другие вещи, и что беспокойство по поводу веса на 2-3 уровня не помогает Ваше здоровье)

WIllJBD
источник
2
принято и, по сути, согласен, но слышал, что средний уровень потребления iphone (включая веб-сервисы / сайты, поддерживающие его использование) составляет примерно такое же количество энергии в год, что и средний холодильник для домашнего хозяйства в США. Поэтому мы, как разработчики, обязаны принимать во внимание этот вид воздействия на окружающую среду. Очевидно, это всегда уравновешивающее действие: время, затраты, производительность, стабильность, и в целом я согласен с вашей точкой зрения - но просто подумайте, что мы должны также рассмотреть этот вид воздействия. Очевидно, что обслуживание / расширяемость входит и здесь. Во всяком случае - точка зрения и спасибо.
MemeDeveloper
Поймите, что конкретный вопрос касается обработки на устройстве, а не в Интернете, но я имею в виду мой комментарий в качестве общего замечания о приоритетах как разработчиках, а не об особенностях ОП.
MemeDeveloper
11

Основная причина, по которой вложенные веса являются плохими, заключается в том, что когда в макете есть дочерние элементы с весом, его необходимо измерять дважды (я думаю, что это упоминается в предупреждении о задержке). Это означает, что взвешенный макет, который также содержит взвешенный макет, должен измеряться четыре раза, и каждый добавляемый вами «слой» весов увеличивает меры со степенью двойки.

В ICS (уровень API 14) GridLayoutбыл добавлен элемент, который позволяет использовать простые и «плоские» решения для многих макетов, для которых ранее требовались весовые коэффициенты. Если вы разрабатываете для более ранних версий Android, вам будет немного сложнее снимать веса, но использование RelativeLayoutи выравнивание максимально возможного размера вашего макета в этой кабине обычно удаляет много вложенных весов.

Jave
источник
9
Я не думаю, что вы можете достичь тех же результатов с GridLayout или RelativeLayout . Например GridLayout: «GridLayout не обеспечивает поддержку принципа веса, как определено в весе. В общем, поэтому невозможно настроить GridLayout для распределения избыточного пространства между несколькими компонентами».
Тимммм
Начиная с API 21, понятие веса было добавлено к GridLayout. Для поддержки старых устройств Android вы можете использовать GridLayout из библиотеки поддержки v7. android.support.v7.widget.GridLayout
Эвансгелист Evansgelist
2

Существует простое решение, позволяющее избежать вложенных LinearLayouts с весами - просто используйте Tablelayout с weightSum и вложенный LinearLayout с weightSum - Tablelayout имеет те же атрибуты, что и LinearLayout (ориентация, weightSum, layout_weight и т. Д.) И не показывает сообщение - "вложенные веса плохо для производительности

Пример:

 <TableLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:weightSum="1">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.8"/>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.2"
            android:orientation="horizontal"
            android:weightSum="1">


            <ImageView
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_weight="0.4"/>

            <TextView
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_weight="0.6"/>


            </LinearLayout>

    </TableLayout>
eneyovich
источник
1

Я думаю, что единственной альтернативой является создание функции, которая будет вызываться onResume и будет устанавливать все размеры и позиции. В любом случае, по весу вы можете установить только размеры, но не отступы (таким образом, макеты становятся еще более сложными), нет textSize (невозможно это как-то компенсировать), не говоря уже о таких вещах, как количество строк.

Гангнус
источник