Die Gefahr der Verwendung von kotlin.syntetic for block in layout

Foto von Justin Chrn auf Unsplash

Nun, mit dem Aufkommen von Kotlin in der Entwicklung für Android, ist ein nützliches Tool aufgetaucht, um Ansichten von xml-layout an Klassen zu binden. Dies ist kotlinx.android.synthetic. Es besteht keine Notwendigkeit mehr, die Methode findViewById() zu verwenden. Es reicht aus, den Wert der id, die in xml angegeben ist, zu schreiben, und man kann die Ansicht in der Klasse verwenden.es gibt viele Artikel darüber, wie zum Beispiel die offizielle Beschreibung. Aber es kann nicht offensichtliche Probleme mit der Verwendung des Tags <include> im Layout geben. Lassen Sie uns ein kleines Beispiel erstellen und versuchen, einen solchen Fall zu zeigen.

Die Testanwendung ist eine Liste mit zwei Elementen, von denen jedes eine Schaltfläche mit Text enthält. Zunächst werden Layouts für die Einträge erstellt – item1.xml und item2.xml. Der Hintergrund hinter der Schaltfläche hat verschiedene Farben für eine bessere Sichtbarkeit.

Lassen Sie uns darauf konzentrieren, dass die Schaltflächen in den Elementen die gleiche ID „Schaltfläche“ haben. Das ist eine wichtige Sache.

Nächste fügen Sie diese Elemente zu main_layout mit Hilfe <include> Tag:

Nun lassen Sie uns es in der Klasse als Layout verwenden:

Starten Sie die Anwendung, um das folgende Ergebnis zu erhalten:

Problemerkennung

Nun machen wir ein kleines Feature, und ändern den Text der Buttons im Code. Es wird einen neuen Text „Changed Text First Item“ für die erste Schaltfläche und „Changed Text Second Item“ für die zweite Schaltfläche geben. Für die Bindung an die Schaltflächen wird kotlinx.synthetic mit alias:

import kotlinx.android.synthetic.main.item1.button as button1
import kotlinx.android.synthetic.main.item2.button as button2

Es ist offensichtlich, dass Schaltfläche1 aus item1.xml und Schaltfläche2 aus item2.xml stammt. Als nächstes ändern wir den Text bei OnCreate:

Lassen wir die App laufen und sehen uns das Ergebnis an:

Oops! Das ist nicht das, was wir erwartet haben. Der Text der ersten Schaltfläche wurde in den Text geändert, der für die zweite Schaltfläche geschrieben wurde, und der Text der zweiten Schaltfläche wurde überhaupt nicht geändert.

Erklärung des Problems

Lassen Sie uns versuchen zu verstehen, was der Grund für dieses Ergebnis ist. Schauen wir uns an, wie die Synthetik unter der Haube funktioniert. Dazu dekompiliere die Kotlin-Klasse nach Java (Show Kotlin Bytecode -> Decompile for AndroidStudio). Jetzt sieht MainActivity wie folgt aus:

Jetzt können wir verstehen, wie die Synthetik funktioniert. Die Activity hat eine HashMap, die die ID der View als Schlüssel und das View-Objekt als Wert verwendet. Sie wird durch faule Initialisierung gefüllt. In unserem Fall sucht der erste Aufruf von button1 nach dem HashMap-Wert mit dem Schlüssel id = R.id.button. Da es einen solchen Wert noch nicht gibt, fügt die Methode ein Paar zur Map hinzu, wobei id der Schlüssel und ein Button-Objekt aus item1 der Wert ist. Das Ergebnis ist, dass der Text für die erste Schaltfläche erfolgreich angewendet wird.

Der Aufruf von button2, der ebenfalls id = R.id.button hat, prüft den Map-Wert für diesen Schlüssel, findet unsere erste Ansicht (die Schaltfläche aus dem ersten Element) und füllt sie mit dem Wert für die zweite Schaltfläche. Das Ergebnis: Die erste Schaltfläche ändert den Text zweimal, die zweite kein einziges Mal

Problemlösung

Als erstes kann man für jede Ansicht eine andere id verwenden. Aber wenn es nicht nützlich ist, kann man zu findViewById zurückkehren:

Lassen Sie uns die App ausführen und das Ergebnis sehen:

Nun funktioniert es richtig!

Fazit

Neue Funktionen der Sprache sind sehr nützlich, aber man sollte verstehen, wie sie funktionieren, um Probleme zu vermeiden.

Danke fürs Lesen dieses Artikels! Ich hoffe, er ist nützlich für Sie

Schreibe einen Kommentar