Dlaczego zagnieżdżone wagi źle wpływają na wydajność? Alternatywy?

160

Napisałem kilka plików układu, w których użyłem layout_weightatrybutu, aby utworzyć stosunek między różnymi widokami.

W pewnym momencie zaczynam otrzymywać ostrzeżenia o zagnieżdżonych wagach.

Zastanawiam się więc, dlaczego zagnieżdżone wagi są niekorzystne dla wydajności i czy istnieje bardziej efektywny sposób tworzenia stałego stosunku między wymiarami widoku, który można by wykorzystać dla różnych rozmiarów ekranu i który nie musi określać wielu wartości wymiarów dpi przez kilka plików układu (mam na myśli różne rozmiary ekranu).

Dziękuję Ci!

MobileCushion
źródło
2
Niesamowity post dla programisty Layout Optimization developer.android.com/training/improving-layouts/…
Muhammad Babar

Odpowiedzi:

140

Zagnieżdżone wagi są niekorzystne dla wydajności, ponieważ:

Wagi układów wymagają dwukrotnego pomiaru widżetu. Gdy LinearLayout z niezerowymi wagami jest zagnieżdżony wewnątrz innego LinearLayout z niezerowymi wagami, liczba pomiarów rośnie wykładniczo.

Lepiej jest używać RelativeLayout i dostosowywać widok do miejsc innych widoków bez używania określonych wartości dpi.

Płyta CD
źródło
87
Dobrze jest być świadomym, co, jak przypuszczam, jest celem wiadomości. I byłoby pamiętać, że gwałtowny wpływ jest jeszcze malutki, jeśli wykładnik jest mała. Dla małych głębokościach gniazdowania, aby nie korzystać z CPU wymaga, aby to zrobić jest jak wół roboczy, który Cię pieścić cały tydzień i tylko wyprowadzać na spacery w niedziele. Mimo to, jeśli chodzi o zagnieżdżanie się na dużych głębokościach, jest to dobry punkt.
Carl
14
RelativeLayout również wymaga dwukrotnego pomiaru, aby upewnić się, że wszystkie jego układy podrzędne są prawidłowe, więc zmiana LinearLayout z wagą układu na RelativeLayout może nie poprawić wydajności.
Piasy
Względny układ nie zawsze działa. W przypadkach, w których musisz skonstruować proporcjonalne widżety
Abdurakhmon
67

Aktualizacja: Jak wiemy, biblioteka procentowego wsparcia jest przestarzała z poziomu API 26. ConstraintLayoutto nowy sposób na osiągnięcie tej samej płaskiej struktury XML.

Zaktualizowany projekt Github

Zaktualizowane próbki:

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

Aktualizacja: Świetna wiadomość, biblioteka procentowa obsługi Androida rozwiązuje nasz problem z wydajnością i zagnieżdżoną, niechlujną wagąLinearLayout

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

Demo TUTAJ

Rozważ ten prosty układ, aby zademonstrować to samo.

procent wsparcia demo libray

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

Uniknięto degradacji wydajności zagnieżdżonej LinearLayoutz obciążeniami. Naprawdę niesamowite !!!.

nitesh
źródło
@dan Tak, biorąc pod uwagę, że mamy zagnieżdżony układ liniowy z wagami.
nitesh
3
„Ta klasa została wycofana na poziomie API 26.0.0-beta1. Zamiast tego rozważ użycie ConstraintLayout i powiązanych układów”. developer.android.com/reference/android/support/percent/…
saiyancoder
7
Nie podoba mi się ConstraintLayout. Dla mnie nie zachowuje się intuicyjnie
Carson Holzheimer
8
ConstraintLayout jest dla mnie bardzo trudny
BertKing
1
być może wyjaśnienia podane przez firmę Apple na temat ograniczeń autoukładu są jaśniejsze, a ponieważ logika jest taka sama, może pomóc. Niestety, uważam, że ConstraintLayout droida jest bardziej ciężki / rozwlekły w użyciu niż AutoLayout iOS
AdricoM
46

Myślę (i prawdopodobnie będę za to podpalony), ale znowu myślę, że mój telefon ma czterordzeniowy procesor, który może konkurować (jeśli nie całkowicie zniszczyć) większość domowych komputerów PC.

Myślę też, że tego rodzaju możliwości sprzętowe to przyszłość telefonów.

Więc dochodzę do wniosku, że dopóki nie dasz się ponieść zagnieżdżeniu (w MHO układ nigdy nie powinien być głębszy niż 4 poziomy, a jeśli tak, to prawdopodobnie robisz to źle), twój telefon mógłby się mniej przejmować o posiadaniu ciężarów.

Jest wiele rzeczy, które możesz zrobić, a które będą miały znacznie większy wpływ na wydajność, niż martwienie się, że procesor wykona dodatkowe obliczenia.

(proszę zauważyć, że jestem trochę zabawny, więc nie traktuję niczego zbyt poważnie z tego postu, poza tym, że są inne rzeczy, które powinieneś najpierw zoptymalizować, a martwienie się o 2-3-poziomową wagę nie pomaga Twoje zdrowie)

WIllJBD
źródło
2
i zasadniczo się z tym zgadzam, ale słyszałem, że przeciętny iPhone zużywa (w tym serwisy / witryny internetowe, które obsługują jego użycie) mniej więcej tyle samo energii rocznie, co przeciętna lodówka w USA. Dlatego naszym obowiązkiem jako deweloperów jest uwzględnienie tego rodzaju wpływu na środowisko. Oczywiście zawsze jest to równowaga: czas, koszty, wydajność, stabilność i ogólnie zgadzam się z twoją perspektywą - ale pomyśl, że powinniśmy również wziąć pod uwagę ten rodzaj wpływu. Oczywiście chodzi tu również o konserwację / rozszerzalność. W każdym razie - uwaga i dzięki.
MemeDeveloper
Zdaj sobie sprawę, że konkretny punkt dotyczy przetwarzania na urządzeniu, a nie w Internecie, ale mam na myśli mój komentarz jako ogólny punkt dotyczący priorytetów jako programistów, a nie szczegółów PO.
MemeDeveloper
11

Głównym powodem, dla którego zagnieżdżone wagi są złe, jest to, że kiedy układ ma dzieci z wagą, należy go zmierzyć dwukrotnie (myślę, że jest to wspomniane w ostrzeżeniu o kłaczkach). Oznacza to, że układ ważony, który zawiera również układ ważony, musi być mierzony czterokrotnie, a każda dodana „warstwa” wag zwiększa miary o potęgę dwa.

W ICS (poziom API 14) GridLayoutdodano, co pozwala na proste i „płaskie” rozwiązania dla wielu układów, które wcześniej wymagały wag. Jeśli tworzysz dla wcześniejszych wersji Androida, będziesz miał nieco trudniejszy czas na usunięcie ciężarów, ale użycie RelativeLayouti spłaszczenie jak największej części układu w tej kabinie zwykle usuwa wiele zagnieżdżonych obciążeń.

Jave
źródło
9
Myślę, że nie można osiągnąć takich samych wyników za pomocą GridLayout lub RelativeLayout . Na przykład GridLayout: „GridLayout nie obsługuje zasady wagi, zgodnie z definicją wagi. Ogólnie nie jest zatem możliwe skonfigurowanie GridLayout w celu rozłożenia nadmiaru przestrzeni między wieloma komponentami”.
Timmmm
Począwszy od API 21 pojęcie wagi zostało dodane do GridLayout. Aby obsługiwać starsze urządzenia z systemem Android, możesz użyć GridLayout z biblioteki obsługi wersji 7. android.support.v7.widget.GridLayout
Эвансгелист Evansgelist
2

Istnieje proste rozwiązanie pozwalające uniknąć zagnieżdżonych układów LinearLayout z wagami - po prostu użyj Tablelayout z weightSum i zagnieżdżonym LinearLayout z weightSum - Tablelayout ma te same atrybuty co LinearLayout (orientacja, wagaSum, layout_weight itp.) I nie wyświetla komunikatu - „zagnieżdżone wagi mają zły wpływ na wydajność ”

Przykład:

 <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
źródło
1

Myślę, że jedyną alternatywą jest utworzenie funkcji, która nazywałaby się onResume i ustawiałaby wszystkie rozmiary i pozycje. W każdym razie, według wagi możesz ustawić tylko rozmiary, ale bez dopełnienia (więc układy stają się jeszcze bardziej skomplikowane), bez textSize (niemożliwe jakoś to skompensować), nie mówiąc już o takich rzeczach jak liczba linii.

Gangnus
źródło