Warum wird 0dp als Leistungssteigerung angesehen?

75

Eine Antwort am Ende dieser Frage wurde ausgefüllt und kombiniert Bemerkungen und Lösungen.

Frage

Ich habe mich umgesehen, aber nichts gefunden, was wirklich erklärt, warum Android Lint sowie einige Eclipse- Hinweise vorschlagen, einige layout_heightund layout_widthWerte durch zu ersetzen 0dp.

Zum Beispiel habe ich eine ListView, die vorgeschlagen wurde, geändert zu werden

Vor

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

Nach

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
</ListView>

In ähnlicher Weise wurden Änderungen an einem ListView-Element vorgeschlagen . Diese sehen vor und nach den Änderungen alle gleich aus, aber ich bin daran interessiert zu verstehen, warum dies Leistungssteigerer sind.

Hat jemand eine Erklärung warum? Wenn es hilft, ist hier das allgemeine Layout mit dem 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>

Antworten

Ich gebe hier eine Antwort ein, weil es wirklich eine Kombination aus Antworten und Links ist, auf die unten verwiesen wird. Wenn ich in etwas falsch liege, lass es mich wissen.

Von Was ist der Trick mit 0dip layout_height oder layouth_width?

Es gibt 3 allgemeine Layoutattribute, die mit Breite und Höhe arbeiten

  1. android:layout_height
  2. android:layout_width
  3. android:layout_weight

Wenn eine LinearLayoutist vertikal , dann ist das layout_weightdie Wirkung der Höhe des Kindes View(s ListView). Durch Setzen von layout_heightto 0dpwird dieses Attribut ignoriert.

Beispiel

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

Wenn eine LinearLayoutist horizontal , dann ist das layout_weightdie Bewirkung Breite des Kindes View(s ListView). Durch Setzen von layout_widthto 0dpwird dieses Attribut ignoriert.

Beispiel

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

Der Grund, das Attribut ignorieren zu wollen, ist, dass wenn Sie es nicht ignorieren, es verwendet wird, um das Layout zu berechnen, das mehr CPU-Zeit benötigt.

Dies verhindert außerdem Verwirrung darüber, wie das Layout aussehen soll, wenn eine Kombination der drei Attribute verwendet wird. Dies wird vom @ android-Entwickler in einer Antwort unten hervorgehoben.

Auch Android Lint und Eclipse sagen beide zu verwenden 0dip. Von der Antwort unten, können Sie verwenden 0dip, 0dp, 0pxusw. , da eine Null - Größe ist das gleiche in einen der Einheiten.

Vermeiden Sie wrap_content in ListView

Aus Layoutbreite einer ListView

Wenn Sie sich jemals gefragt haben, warum getView(...)so oft angerufen wird wie ich, stellt sich heraus, dass es damit zusammenhängt wrap_content.

Wenn Sie wrap_contentwie oben verwenden, werden alle untergeordneten ViewElemente gemessen, was zu einer weiteren CPU-Zeit führt. Diese Messung führt dazu getView(...), dass Sie angerufen werden. Ich habe dies jetzt getestet und die Anzahl der Aufrufe getView(...)wird drastisch reduziert.

Wenn ich wrap_contentauf zwei ListViews verwendet habe, getView(...)wurde 3 Mal für jede Zeile auf einer ListViewund 4 Mal für jede Zeile auf der anderen aufgerufen .

Dies zu ändern , auf die empfohlene 0dp, getView(...)wurde für jede Zeile nur einmal aufgerufen. Dies ist eine ziemliche Verbesserung, hat aber mehr mit dem Vermeiden wrap_contentvon a zu tun als mit ListViewdem 0dp.

Der Vorschlag von 0dpverbessert jedoch die Leistung aus diesem Grund erheblich.

Kirche
quelle
1
Ähnlich hier stackoverflow.com/questions/7220404/…
Haresh Chaudhary
1
Schöner Fund, den habe ich nicht gefunden. Die Antwort, die nicht akzeptiert wurde, ist die, die es erklärt
Kirk
Es hat mich umgehauen zu sehen, dass die Frage mehr Stimmen hat als die Top-Antwort, aber jetzt verstehe ich warum. Erstaunliche Fragen und Antworten. Wenn Sie dazu bereit sind, würde dies zu einem großartigen Community-Wiki führen. Danke dafür!
RileyE

Antworten:

24

Zuallererst haben Sie dies,

<ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

Nehmen Sie niemals die Höhe der ListView als wrap_content, da dies zu Problemen führen kann. Hereist der Grund dafür und this answer.

Außerdem,

Ich habe mich umgesehen, aber nichts gefunden, was wirklich erklärt, warum Android Lint sowie einige Eclipse-Hinweise vorschlagen, einige Werte für layout_height und layout_width durch 0dp zu ersetzen.

Weil Sie dies verwenden layout_weight = "1", bedeutet dies , dass Ihre ListView die Höhe so hoch nimmt, wie sie verfügbar ist. In diesem Fall müssen Sie es nicht layout_height = "wrap_content"einfach ändern, android:layout_height="0dp"und die Höhe von ListView wird von verwaltet layout_weight = "1".

Lalit Poptani
quelle
12

Wenn also android: layout_weight in View X verwendet wird und LinearLayout horizontal ist, wird Xs android: layout_width einfach ignoriert.

Ähnlich ist es, wenn android: layout_weight in View X verwendet wird und LinearLayout vertikal ist, dann wird Xs android: layout_height ignoriert.

Dies bedeutet tatsächlich, dass Sie alles in diese ignorierten Felder einfügen können: 0dp oder fill_parent oder wrap_content. Es spielt keine Rolle. Es wird jedoch empfohlen, 0dp zu verwenden, damit Ansichten ihre Höhe oder Breite nicht extra berechnen (was dann ignoriert wird). Dieser kleine Trick spart einfach CPU-Zyklen.

von :

Was ist der Trick mit 0dip layout_height oder layouth_width?

Archie.bpgc
quelle
5

Soweit ich weiß, gibt es einen Unterschied zwischen der Verwendung von 0dp (oder 0px übrigens, es ist das gleiche, da 0 0 ist, egal was die Einheit hier ist) und dem wrap_content oder fill_parent (oder match_parent, es ist das gleiche).

es hängt vom Gewicht ab, das Sie verwenden. Wenn Sie nur das Gewicht 1 verwenden, sehen alle gleich aus, aber die Bedeutung ist immer unterschiedlich und für die Leistung wichtig.

Um dies zu zeigen, versuchen Sie Folgendes:

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

und versuchen Sie dann, die 0px durch match_parent zu ersetzen. Sie werden sehen, dass das Ergebnis sehr unterschiedlich ist.

Normalerweise möchten Sie zum besseren Verständnis und für eine bessere Leistung 0px verwenden.

Android-Entwickler
quelle
3

LinearLayoutMisst alle Kinder gemäß den layout_width/ layout_height-Werten und teilt dann den verbleibenden Raum (der negativ sein kann) gemäß den layout_weightWerten auf.

0dpist effizienter als wrap_contentin diesem Fall, da es effizienter ist, nur Null für die ursprüngliche Größe zu verwenden und dann die volle Größe des Elternteils basierend auf dem Gewicht zu teilen, als zuerst das Kind zu messen und dann den Rest basierend auf dem Gewicht zu teilen.

Die Effizienz ergibt sich also daraus, dass das Kind nicht gemessen wird. 0dpsollte genau so effizient sein (und genau das gleiche Ergebnis liefern) wie match_parentoder 42pxoder eine andere feste Zahl.

Karu
quelle
1

Vorsicht bei der Verwendung von Android: layout_height = "0dp"

Ich habe festgestellt, dass in einer ListView (mit der empfohlenen Ansicht Recycling mit convertView, siehe z. B. http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ ) android: layout_height = " 0dp "für die Zeile TextView kann zu Textkürzungen für mehrzeiligen Textinhalt führen.

Immer wenn ein TextView-Objekt, das zuvor zum Anzeigen eines Textes verwendet wurde, der in eine einzelne Zeile passt, recycelt wird, um einen längeren Text anzuzeigen, der mehr als eine Zeile benötigt, wird dieser Text auf eine einzelne Zeile gekürzt.

Das Problem wird mit Android behoben: layout_height = "wrap_content"

Damien
quelle