Why are nested weights bad for performance? Alternatives?
Asked Answered
V

6

174

I have written a couple layout files where I used the layout_weight attribute to create a ratio between different views.

At some point, I start getting lint warnings about nested weights.

So, I wonder why are nested weights bad for performance, and if there is a more efficient way to create a constant ratio between view dimensions that could be used for different screen sizes and that doesn't need to specify a lot of dimension dpi values throught several layout files (for different screen sizes, I mean).

Thank you!

Vincennes answered 24/2, 2012 at 12:26 Comment(1)
An awesome post for Layout Optimization developer.android.com/training/improving-layouts/…Logos
E
149

Nested weights are bad for performance because:

Layout weights require a widget to be measured twice. When a LinearLayout with non-zero weights is nested inside another LinearLayout with non-zero weights, then the number of measurements increase exponentially.

It's better to use RelativeLayouts and adjust your view according to the places of other views without using specific dpi values.

Endocardial answered 24/2, 2012 at 12:51 Comment(3)
Good thing to be aware of, which I suppose is the purpose of the message. I would note that an exponential impact is still tiny if the exponent involved is small. For small depths of nesting, to not use the CPU required to do this is like having a workhorse that you pamper all week and only lead out for walks on Sundays. Still, for large depths of nesting, it's a point well taken.Ugh
RelativeLayout also need measure twice to make sure all its children layout properly, so change LinearLayout with layout weight to RelativeLayout may not improve the performance.Ondine
Relative layout does not always work. In cases where you need to construct proportional widgetsUnwitnessed
H
70

Update: As we know the percent support library is deprecated from API level 26. ConstraintLayout is the new way to achieve the same flat xml structure.

Updated Github Project

Updated Samples:

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

Update: Great news android percent support library solves our problem of performance and nested messy weighted LinearLayout

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

Demo HERE

Consider this simple layout to demonstrate the same.

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

Avoided performance degrader nested LinearLayout with weights.Really awesome!!!.

Highflown answered 6/9, 2015 at 8:11 Comment(6)
@dan Yes considering we have nested linear layout with weights.Highflown
"This class was deprecated in API level 26.0.0-beta1. consider using ConstraintLayout and associated layouts instead." developer.android.com/reference/android/support/percent/…Cheery
I don't like ConstraintLayout. It doesn't behave intuitively for mePreraphaelite
the ConstraintLayout is so difficult for meHeterography
maybe the explanations given by apple on autolayout constraints are clearer, and as the logic is the same, it can help. Unfortunately I find droid's ConstraintLayout more heavy/verbose to use than iOS' AutoLayoutPrint
it seems app:layout_constraintVertical_weight="1" & app:layout_constraintHorizontal_weight="1" has a lot better performance compare to using app:layout_constraintHeight_percent & app:layout_constraintWidth_percentLucienlucienne
K
49

I think (and I will probably be flamed for this), but again I think my phone has a quad core processor to rival (if not utterly destroy) most peoples home PC's.

I also think this kind of hardware capability is the future of phones.

So I come to a conclusion, that as long as you are not getting carried away with nesting (in MHO a layout should never be more then 4 levels deep, and if it is you are probably doing it wrong), your phone could care less about having weights.

There are many things you can do that will have a much more far reaching effect on performance, then worrying about your processor doing some extra math.

(please note that I am being slightly humorous, and so not to take anything too seriously from this post, other then the idea that there are other things you should optimize first, and that worrying about a 2-3 level deep weight is not helping your health)

Kherson answered 8/8, 2013 at 22:25 Comment(2)
taken, and essentially agree, but have heard the average iphone uses (including the web services / site that support it's use) around the same amount of energy a year as the average US household fridge. It is therefore our responsibility as developers to take this kind of environmental impact into consideration. Obviously its always a balancing act: time, costs, performance, stability, and generally I do agree with your perspective - but just think we should also consider this kind of impact. Obviously maintenance / extensibility comes in here also. Anyhow - point made and thanks.Frescobaldi
Realise the specific point in question is about processing on the device not the web, but mean my comment as a general point about priorities as developers more than specifics of the OP.Frescobaldi
T
11

The main reason why nested weights are bad is that when a layout has children with a weight, it has to be measured twice (I think this is mentioned in the lint-warning). This means that a weighted layout that also contains a weighted layout has to measured four times, and each 'layer' of weights you add increase the measures with a power of two.

In ICS (API level 14) the GridLayout was added, which allows simple and 'flat' solutions for many layouts which previously required weights. If you are developing for earlier versions of Android you will have a slightly harder time removing weights, but using a RelativeLayout and flattening as much as possible of your layout into that cab usually remove a lot of the nested weights.

Toga answered 24/2, 2012 at 12:52 Comment(2)
I don't think you can achieve the same results with GridLayout or RelativeLayout. E.g. for GridLayout: "GridLayout does not provide support for the principle of weight, as defined in weight. In general, it is not therefore possible to configure a GridLayout to distribute excess space between multiple components."Hemorrhoid
Starting in API 21 the notion of weight was added to GridLayout. To support older android devices, you can use the GridLayout from the v7 support library. android.support.v7.widget.GridLayoutDonaghue
M
3

There is an easy solution to avoid nested LinearLayouts with weights - just use Tablelayout with weighSum and nested LinearLayout with weightSum - Tablelayout has the same attributes as LinearLayout(orientation, weightSum, layout_weight, etc.) and doesn't show message - "nested weights have bad for performance"

Example:

 <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>
Modesta answered 25/3, 2019 at 20:46 Comment(0)
L
1

I think, the only alternative is to make a function that would be called onResume and will set all sizes and positions. Anyway, by weight you can set only sizes but no padding's (so layouts become even more complicated), no textSize's (impossible to compensate this somehow), let alone such things as number of lines.

Lawanda answered 24/2, 2012 at 12:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.