Effizienz findViewById
Wahrscheinlich die meisten Android-Entwickler wissen, dass findViewById
ist nicht Billig Betrieb. Eine andere Sache, dass die meisten von uns wissen, ist, dass Sie Sie können erhöhen Sie die Leistungsfähigkeit durch die Verwendung der kleinsten sub-Baum der view-Hierarchie zu finden, sichten durch Ihre id, Beispiel:
<LinearLayout
android:id="@+id/some_id_0">
<LinearLayout
android:id="@+id/some_id_1">
<LinearLayout
android:id="@+id/some_id_2">
<TextView android:id="@+id/textview" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
In diesem Fall möchten Sie wahrscheinlich die Suche im LinearLayout
mit der id == @id/textview
Aber was ist der Fall, wenn die Hierarchie nicht Kaskadierung, sondern Verzweigungen auf jeder Ebene, und Sie möchten den Blick auf die "Blätter" lassen Sie uns sagen? Führen Sie die findViewById
man die Unterseite der Zweig, durch das finden Eltern, ODER führen Sie die findViewById
auf eine größere Teilmenge? Ich denke, eine einfache Antwort wäre, dass es hängt von der Fall, aber vielleicht könnten wir verallgemeinern ein bisschen auf was es wirklich hängt?
Dank
EDIT:
Durch eine größere Teilmenge meine ich so etwas wie dieses:
<RelativeLayout android:id="@+id/r0">
<RelativeLayout
android:id="@+id/r1">
<LinearLayout
android:id="@+id/some_id_0">
<LinearLayout
android:id="@+id/some_id_1">
<LinearLayout
android:id="@+id/some_id_2">
<TextView android:id="@+id/textview0" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/some_id_3">
<LinearLayout
android:id="@+id/some_id_4">
<LinearLayout
android:id="@+id/some_id_5">
<TextView android:id="@+id/textview1" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/some_id_6">
<LinearLayout
android:id="@+id/some_id_7">
<LinearLayout
android:id="@+id/some_id_8">
<TextView android:id="@+id/textview2" />
<TextView android:id="@+id/textview3" />
<TextView android:id="@+id/textview4" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
So wäre die Frage, wenn ich will findViewById
die TextView
Blick in LinearLayout
mit @+id/some_id_8
sollte ich ausführen dieses Vorgangs auf die ganze Packung, oder sollte ich findViewById
die LinearLayout
mit @+id/some_id_8
und auf diese Ansicht findViewById
alle TextViews
?
- Können Sie erklären, mehr Ihr 2 alternativen, vor allem die "findViewById auf eine größere Untermenge" ?
- Überprüfen Sie bitte mein edit.
- Standard-traversal ist Tiefe ersten. Das finden einer Teilstruktur erste riecht wie Mikro-Optimierung, das macht den code etwas schwieriger zu pflegen. Messen, um herauszufinden, ob es wirklich einen Unterschied macht
- Als laalto bereits erwähnt findViewById() iteriert über den gesamten view-Hierarchie, so dass mit den beiden findViewById () - Aufrufe wird keinen Unterschied machen(außer Sie haben eine zusätzliche Zeile code). Wenn Sie eine intime Kenntnis über die view-Hierarchie könntest du eine Kombination von getChild() und findViewById (), die sollte schneller sein in einigen casses(nicht, dass es egal), aber werde den code sehr starr, um zukünftige änderungen. In das Ende, das die Tiefe und die Größe der view-Hierarchie werden wichtiger für die performance dann suchen diese Ansichten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Macht es absolut keinen Unterschied, ob Sie sich für die
View
direkt oder wenn man sich für ein Elternteil und erst dann das Kind. Aber wenn Sie zum Beispiel wollen Sie zum abrufen der dreiTextViews
imLinearLayout
mit der idsome_id_8
dann wäre es besser für die Leistung wenn Sie ersten Blick für dieLinearLayout
und dann für dieTextViews
. Aber der Unterschied ist verschwindend klein. Das eigentliche problem ist das layout selbst (mehr dazu weiter unten).Und in der Regel
findViewById()
ist nicht die Quelle allen übels. Es kann sein, ein problem in einemListView
wenn Sie anrufenfindViewById()
möglicherweise sogar mehrere Male während jedergetView()
nennen, aber das ist es, was die Ansicht Halter pattern ist für.Wenn die Leistung entscheidend ist, dass Sie rufen
findViewById()
so wenig wie möglich. In einemFragment
oderActivity
Sie Aussehen kann für alle dieViews
Sie jemals brauchen werden, inonCreateView()
oderonCreate()
. Wenn Sie speichern die Verweise in ein paar member-Variablen, die Sie nie haben, es zu nennen, wieder.Nun zu erklären, warum
findViewById()
kann ein performance-problem, das wir haben, um einen Blick auf seine Umsetzung, dieser link führt zur Android 4.4.4 View source code:So
findViewById()
nur überprüft, ob die id gültig ist, und wenn es dann die protected-MethodefindViewTraversal()
genannt wird. In einemView
implementiert ist es so:Es nur prüft, ob die übergebene id gleich der id des
View
und zurückthis
wenn Sie es tut, sonstnull
. Der interessante Teil ist diefindViewTraversal()
Umsetzung vonViewGroup
, dieser Link führt zur Android 4.4.4 ViewGroup source-code:Den ersten, wenn an der Spitze dieser Methode ist die gleiche wie in der
View
Umsetzung, es prüft nur, ob die übergebene id entspricht der id desViewGroup
und wenn es tut, gibt sich selbst. Danach durchläuft es die Kinder und fordertfindViewById()
auf jedes der Kinder, wenn der Rückgabewert dieses Aufrufs ist nichtnull
dann dieView
suchen wir für gefunden wurde und zurückgegeben werden.Wenn Sie mehr details darüber, wie
Views
oderViewGroups
Arbeit ich schlage vor, studieren Sie den source-code selbst!Also das scheint alles ziemlich straight-forward. Die view-Hierarchie ist im wesentlichen durchzogen ist wie ein Baum. Und, kann es ziemlich teuer oder ziemlich schnell, je nachdem, wie viele
Views
sind in Ihrem layout. Es spielt keine Rolle, wenn dein layout sieht so aus:Ist oder wenn es sieht wie folgt aus:
Da die Menge der
Views
ist die gleiche in beiden Fällen, und die Leistung vonfindViewById()
skaliert mit der Menge desViews
.ABER die Allgemeine Regel ist, dass man versuchen sollte zu reduzieren die Komplexität des Layouts, um die Leistung zu erhöhen und, dass Sie sollte benutzen oft eine
RelativeLayout
. Und das funktioniert nur, weil, wenn Sie reduzieren die Komplexität Sie reduzieren auch die Menge derViews
in das layout und dieRelativeLayouts
sind sehr gut auf die Reduzierung von Komplexität. Lassen Sie mich veranschaulichen, dass, Bild, Sie haben ein layout wie diese:Vorstellen, dass in diesem Fall sowohl von der
RelativeLayouts
oben sind nur da, um die position des innerenLinearLayouts
auf Besondere Weise die äußerenLinearLayout
ist nur da, um die position derRelativeLayouts
unter einander. Sie können sehr leicht erstellen, die das gleiche layout mit nur einemRelativeLayout
als eine Wurzel und die vierLinearLayouts
als Kinder:Und die Leistung, das layout wird besser sein als das layout oben nicht, weil die
RelativeLayout
ist irgendwie leistungsmäßig besser als einLinearLayout
- und nicht weil das layout flacher, sondern einfach, weil die Menge derViews
im layout ist niedriger. Das gleiche gilt für fast alle anderen view-bezogene Prozesse wie zeichnen, layouten, Messen. Alles wird schneller, nur weil die Höhe derViews
im layout ist niedriger.Und um zurück zu deiner ursprünglichen Frage: Wenn Sie möchten, eine Leistung zu erhöhen als verringern Sie die Komplexität Ihres Layouts. Es gibt absolut keinen Grund zu haben, so viele verschachtelte
LinearLayouts
. Ihre "große Teilmenge" kann fast sicher sein, reduziert dies:Und so eine layout wäre auf jeden Fall Ertrag, einen großen performance-boost.
RelativeLayout is somehow performance-wise better than a LinearLayout
dies scheint 90% falsch für mich.LinearLayout
vieleLinearLayouts
oder einer beliebigen komplexen layout. Sicher eineRelativeLayout
wird Leistung Weise schlechter als einLinearLayout
für viele Grund zum Beispiel der Bedarf für zwei-layout geht inRelativeLayouts
etc. Jedoch wenn Sie verwenden dieRelativeLayout
für den Zweck gemacht für - das erstellen von komplexen relativen layouts die zimmerreserviereung, ohne das nest viele layouts dann dieRelativeLayout
wirklich glänzt. Natürlich ist heute alles anders ist. DieCoordinatorLayout
mit seinenBehaviors
ist extrem flexibel und sehr komplizierten layouts umgesetzt werden können, sind mit einem snap.CoordinatorLayout
, aber immer noch dieRelativeLayout
ist gut für genau den Zweck, für: Zur Vereinfachung der layouts. Ich meine, schauen Sie sich nur die vielen verschachtelten layouts in Frage. Glaubst du wirklich, dass alle diejenigen, dieLinearLayouts
performance-Weise besser als nur mit einemRelativeLayout
? Und das ist genau das, was meine Antwort ist.layout_margin
undlayout_gravity
. Es ist nicht ordentlich und man kann nicht immer tun, aber Sie erhalten die gleiche Flachheit und ich habe gesehen, große Verbesserungen in der Leistung, meist in der adapter-Ansichten.FrameLayout
s sind groß, wenn Sie Ihnen den rechten Weg.layout_gravity
gibt Ihnen viel Freiheit bei der Platzierung vonViews
und den gesamten mess-und Layout-Prozess von einemFrameLayout
ist schnell. Aber dann wieder das ist, was macht dieCoordinatorLayout
so toll, es ist einFrameLayout
mit extra-Funktionen.Blick auf die android-source-code, den ich einfach nicht sehen, wie findViewById ist teuer bei allen. Es ist im Grunde eine einfache Schleife, ich weiß, es ist rekursiv, so werden Sie die Strafe zu bezahlen, der ständig Umschalten der Stacks, aber auch die komplizierteste Bildschirm wird in der Reihenfolge der Dutzende von Ansichten, die nicht Tausende, außer für Recycling-Listen. Ich denke, wir brauchen benchmarks, die auf low-end-Geräte, zu wissen, ob es wirklich ein Problem.