Perché i pesi nidificati sono dannosi per le prestazioni? Alternative?


160

Ho scritto un paio di file di layout in cui ho usato l' layout_weightattributo per creare un rapporto tra diverse viste.

Ad un certo punto, comincio a ricevere avvisi di lanugine sui pesi nidificati.

Quindi, mi chiedo perché i pesi nidificati siano negativi per le prestazioni e se esiste un modo più efficiente per creare un rapporto costante tra le dimensioni della vista che potrebbe essere utilizzato per dimensioni dello schermo diverse e che non debba specificare molti valori dpi dimensione attraverso diversi file di layout (per dimensioni dello schermo diverse, intendo).

Grazie!


2
Un post fantastico per l'ottimizzazione del layout developer.android.com/training/improving-layouts/…
Muhammad Babar

Risposte:


140

I pesi nidificati sono dannosi per le prestazioni perché:

I pesi di layout richiedono che un widget sia misurato due volte. Quando un LinearLayout con pesi diversi da zero è nidificato all'interno di un altro LinearLayout con pesi diversi da zero, il numero di misurazioni aumenta esponenzialmente.

È meglio utilizzare RelativeLayout e regolare la vista in base alle posizioni di altre viste senza utilizzare valori dpi specifici.


87
Buona cosa da tenere presente, che suppongo sia lo scopo del messaggio. Mi piacerebbe notare che un impatto esponenziale è ancora molto piccolo se l'esponente in questione è piccola. Per piccole profondità di annidamento, non usare la CPU necessaria per fare questo è come avere un cavallo da lavoro che ti coccoli per tutta la settimana e fai passeggiate solo la domenica. Tuttavia, per grandi profondità di nidificazione, è un punto ben preso.
Carl,

14
Anche RelativeLayout deve essere misurato due volte per assicurarsi che tutto il layout secondario sia corretto, quindi modificare LinearLayout con il peso del layout in RelativeLayout potrebbe non migliorare le prestazioni.
Piasy,

Il layout relativo non sempre funziona. Nei casi in cui è necessario costruire widget proporzionali
Abdurakhmon,

67

Aggiornamento: come sappiamo, la libreria di supporto percentuale è obsoleta dal livello API 26. ConstraintLayoutè il nuovo modo per ottenere la stessa struttura xml piatta.

Progetto Github aggiornato

Esempi aggiornati:

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

Aggiornamento: grandi novità La libreria di supporto percentuale Android risolve il nostro problema di prestazioni e ponderato annidatoLinearLayout

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

Demo QUI

Considera questo semplice layout per dimostrare lo stesso.

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

Evita il degrado delle prestazioni annidato LinearLayoutcon i pesi. Davvero fantastico !!!.


@dan Sì, considerando che abbiamo un layout lineare nidificato con pesi.
notte

3
"Questa classe è stata deprecata nel livello API 26.0.0-beta1. Considera invece l'utilizzo di ConstraintLayout e dei layout associati." developer.android.com/reference/android/support/percent/…
saiyancoder

7
Non mi piace ConstraintLayout. Per me non si comporta in modo intuitivo
Carson Holzheimer,

8
il ConstraintLayout è così difficile per me
BertKing,

1
forse le spiegazioni fornite da Apple sui vincoli di autolayout sono più chiare e, poiché la logica è la stessa, può essere d'aiuto. Sfortunatamente trovo che ConstraintLayout di Droid sia più pesante / dettagliato da usare rispetto a
AutoLayout

46

Penso (e probabilmente sarò infiammato per questo), ma penso di nuovo che il mio telefono abbia un processore quad core per competere (se non distruggere completamente) la maggior parte dei PC domestici.

Penso anche che questo tipo di funzionalità hardware sia il futuro dei telefoni.

Quindi giungo alla conclusione che, fintanto che non ti lascerai trasportare dall'annidamento (in MHO un layout non dovrebbe mai essere più profondo di 4 livelli e se è probabile che tu stia facendo male), al tuo telefono potrebbe importare di meno di avere pesi.

Ci sono molte cose che puoi fare che avranno un effetto molto più ampio sulle prestazioni, quindi preoccuparti del tuo processore che fa un po 'di matematica in più.

(tieni presente che sono un po 'divertente, quindi non prendere nulla di troppo serio da questo post, a parte l'idea che ci sono altre cose che dovresti prima ottimizzare e che preoccuparsi di un peso profondo di 2-3 livelli non aiuta la vostra salute)


2
preso, e sostanzialmente d'accordo, ma ho sentito l'uso medio di iPhone (compresi i servizi web / sito che ne supportano l'uso) circa la stessa quantità di energia all'anno del frigorifero domestico americano medio. È pertanto nostra responsabilità come sviluppatori prendere in considerazione questo tipo di impatto ambientale. Ovviamente è sempre un atto di bilanciamento: tempo, costi, prestazioni, stabilità e in generale sono d'accordo con la tua prospettiva - ma pensa solo che dovremmo considerare anche questo tipo di impatto. Ovviamente qui arriva anche la manutenzione / estensibilità. Comunque - punto fatto e grazie.
MemeDeveloper

Realizzare il punto specifico in questione riguarda l'elaborazione sul dispositivo e non sul web, ma intendo il mio commento come punto generale sulle priorità come sviluppatori più che sui dettagli del PO.
MemeDeveloper

11

Il motivo principale per cui i pesi nidificati sono cattivi è che quando un layout ha bambini con un peso, deve essere misurato due volte (penso che questo sia menzionato nell'avvertenza sui filacci). Ciò significa che un layout ponderato che contiene anche un layout ponderato deve essere misurato quattro volte e ogni "strato" di pesi aggiunto aumenta le misure con una potenza di due.

In ICS (livello API 14) il GridLayout stato aggiunto, che consente soluzioni semplici e "piatte" per molti layout che in precedenza richiedevano pesi. Se stai sviluppando per le versioni precedenti di Android avrai un po 'più tempo a rimuovere i pesi, ma usando un RelativeLayoute appiattendo il più possibile il tuo layout in quella cabina di solito rimuovi molti dei pesi nidificati.


9
Non credo che tu possa ottenere gli stessi risultati con GridLayout o RelativeLayout . Ad esempio GridLayout: "GridLayout non fornisce supporto per il principio di peso, come definito in peso. In generale, non è quindi possibile configurare un GridLayout per distribuire lo spazio in eccesso tra più componenti."
Timmmm,

A partire da API 21 la nozione di peso è stata aggiunta a GridLayout. Per supportare i dispositivi Android meno recenti, è possibile utilizzare GridLayout dalla libreria di supporto v7. android.support.v7.widget.GridLayout
Эвансгелист Evansgelist

2

Esiste una soluzione semplice per evitare LinearLayout nidificati con pesi: basta usare Tablelayout con weightSum e LinearLayout nidificato con weightSum: Tablelayout ha gli stessi attributi di LinearLayout (orientamento, weightSum, layout_weight, ecc.) E non mostra il messaggio: "pesi nidificati avere cattive prestazioni "

Esempio:

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

1

Penso che l'unica alternativa sia quella di creare una funzione che sarebbe chiamata onResume e imposterà tutte le dimensioni e posizioni. Ad ogni modo, in base al peso puoi impostare solo dimensioni ma nessuna imbottitura (quindi i layout diventano ancora più complicati), nessun textSize (impossibile compensarlo in qualche modo), per non parlare di cose come il numero di linee.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.