Dieses Codelab ist Teil des Android Kotlin Fundamentals-Kurss. Sie profitieren von diesem Kurs, wenn Sie nacheinander die Codelabs durcharbeiten. Alle Kurs-Codelabs finden Sie auf der Landingpage für Kotlin-Grundlagen für Android-Entwickler.
Einführung
In vorherigen Codelabs haben Sie die Funktion findViewById()
verwendet, um Verweise auf Datenansichten zu erhalten. Wenn Ihre App komplexe Hierarchien in den Ansichten hat, ist findViewById()
teuer und verlangsamt die App, da Android die Hierarchie über die Hierarchie hinweg durchsucht, bis die gewünschte Ansicht gefunden wird. Zum Glück gibt es die bessere Möglichkeit.
Um Daten in Ansichten festzulegen, haben Sie String-Ressourcen verwendet und Daten aus der Aktivität festgelegt. Es wäre effizienter, wenn die Ansicht die Daten hätte. Glücklicherweise ist das möglich.
In diesem Codelab lernen Sie, wie Sie mit Datenbindungen die Verwendung von findViewById()
überflüssig machen. Außerdem erfahren Sie, wie Sie mithilfe von Datenbindungen direkt aus einer Ansicht auf Daten zugreifen.
Was Sie bereits wissen sollten
Sie sollten mit Folgendem vertraut sein:
- Was eine Aktivität ist und wie Sie sie in
onCreate()
mit einem Layout einrichten. - Textansicht erstellen und Text festlegen, der in der Textansicht angezeigt wird
- Mit
findViewById()
einen Verweis auf eine Ansicht abrufen - Erstellen und Bearbeiten eines einfachen XML-Layouts für eine Ansicht
Lerninhalte
- Wie Sie die Datenbindungsbibliothek verwenden, um ineffiziente Aufrufe von
findViewById()
zu vermeiden. - App-Daten direkt aus XML aufrufen
Aufgaben
- Sie können eine App so ändern, dass die Datenbindung anstelle von
findViewById()
verwendet wird und dass Daten direkt aus den Layout-XML-Dateien abgerufen werden.
In diesem Codelab starten Sie mit der ÜberMe-App und ändern die App so, dass sie Datenbindung verwendet. Ähnlich sieht die App aus.
Vorteile der App „Über mich“:
- Wenn der Nutzer die App öffnet, sieht die App einen Namen, ein Feld für die Eingabe eines Alias, eine Schaltfläche Fertig, ein Sternsymbol und scrollbaren Text.
- Der Nutzer kann einen Alias eingeben und auf die Schaltfläche Fertig tippen. Das bearbeitbare Feld und die Schaltfläche werden durch eine Textansicht ersetzt, die den eingegebenen Alias enthält.
Sie können den Code verwenden, den Sie im vorherigen Codelab erstellt haben, oder den Code AboutMeDataBindung-Starter von GitHub herunterladen.
Der Code, den Sie in vorherigen Codelabs geschrieben haben, verwendet die Funktion findViewById()
, um Verweise auf Aufrufe zu erhalten.
Jedes Mal, wenn Sie mit findViewById()
eine Ansicht suchen, nachdem die Ansicht erstellt oder neu erstellt wurde, durchquert das Android-System die Ansichtshierarchie zur Laufzeit, um sie zu finden. Hat Ihre App nur wenige Aufrufe, ist das kein Problem. Produktions-Apps können jedoch Dutzende von Ansichten in einem Layout haben, und selbst mit dem besten Design sind verschachtelte Ansichten verfügbar.
Stellen Sie sich ein lineares Layout vor, das eine Scrollansicht enthält, die eine Textansicht enthält. Bei einer großen oder Deep-View-Hierarchie kann das Auffinden einer Ansicht so lang dauern, dass die App für den Nutzer dadurch verlangsamt werden kann. Das Speichern von Ansichten in Variablen kann hilfreich sein, aber Sie müssen trotzdem für jede Ansicht in jedem Namespace eine Variable initialisieren. Und es gibt viele Aufrufe und mehrere Aktivitäten.
Eine Lösungsmöglichkeit ist die Erstellung eines Objekts, das einen Verweis auf die einzelnen Ansichten enthält. Dieses Objekt, das als Binding
-Objekt bezeichnet wird, kann von Ihrer gesamten App verwendet werden. Dieses Verfahren wird als Datenbindung bezeichnet. Nachdem ein Bindungsobjekt für Ihre App erstellt wurde, können Sie über das Bindungsobjekt auf die Ansichten und andere Daten zugreifen, ohne die Datenansichtshierarchie durchlaufen oder nach den Daten suchen zu müssen.
Datenbindung bietet folgende Vorteile:
- Code ist kürzer, einfacher zu lesen und leichter zu verwalten als Code, bei dem
findByView()
verwendet wird. - Daten und Datenansichten sind deutlich voneinander getrennt. Dieser Vorteil der Datenbindung wird später in diesem Kurs immer wichtiger.
- Das Android-System durchlaufen die Ansichtshierarchie nur einmal, um jede Datenansicht zu erhalten. Diese erfolgt während des App-Starts, nicht während der Laufzeit, wenn der Nutzer mit der App interagiert.
- Sie erhalten Typsicherheit für den Zugriff auf Datenansichten. Typsicherheit bedeutet, dass der Compiler während der Kompilierung Typen validiert. Beim Versuch, einer Variablen den falschen Typ zuzuweisen, wird ein Fehler ausgegeben.
In dieser Aufgabe richten Sie die Datenbindung ein und verwenden die Datenbindung, um Aufrufe von findViewById()
durch Aufrufe des Bindungsobjekts zu ersetzen.
Schritt 1: Datenbindung aktivieren
Um die Datenbindung zu verwenden, müssen Sie die Datenbindung in Ihrer Gradle-Datei aktivieren, da sie nicht standardmäßig aktiviert ist. Der Grund dafür ist, dass sich durch die Datenbindung die Kompilierungszeit erhöht und sie sich auf die App-Startzeit auswirken kann.
- Wenn Sie die AboutMe-App aus einem früheren Codelab nicht haben, laden Sie den Code AboutMeDataBindung-Starter von GitHub herunter. Öffne es in Android Studio.
- Öffnen Sie die Datei
build.gradle (Module: app)
. - Fügen Sie innerhalb des Abschnitts
android
vor der schließenden geschweiften Klammer einendataBinding
-Abschnitt ein und setzen Sieenabled
auftrue
.
dataBinding {
enabled = true
}
- Synchronisieren Sie das Projekt, wenn Sie dazu aufgefordert werden. Wenn Sie nicht aufgefordert werden, wählen Sie Datei gt; Projekt mit Gradle-Dateien synchronisieren aus.
- Du kannst die App ausführen, es werden aber keine Änderungen angezeigt.
Schritt 2: Layoutdatei so ändern, dass sie mit Datenbindung verwendet werden kann
Um mit der Datenbindung zu arbeiten, müssen Sie Ihr XML-Layout mit einem <layout>
-Tag umschließen. Auf diese Weise ist die Stammklasse nicht mehr eine Datenansichtsgruppe, sondern ein Layout, das Ansichtsgruppen und Ansichten enthält. Das Bindungsobjekt kann dann das Layout und die darin enthaltenen Ansichten kennen.
- Öffnen Sie die Datei
activity_main.xml
. - Wechseln Sie zum Tab Text.
- Fügen Sie
<layout></layout>
als äußerstes Tag um<LinearLayout>
hinzu.
<layout>
<LinearLayout ... >
...
</LinearLayout>
</layout>
- Wählen Sie Code > Code neu formatieren aus, um den Code-Einzug zu korrigieren.
Die Namespace-Deklarationen für ein Layout müssen sich im äußersten Tag befinden.
- Entferne die Namespace-Deklarationen aus
<LinearLayout>
und füge sie in das<layout>
-Tag ein. Das öffnende<layout>
-Tag sollte wie unten dargestellt aussehen und das<LinearLayout>
-Tag sollte nur die Ansichtseigenschaften enthalten.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
- Erstellen Sie Ihre App und führen Sie sie aus, um zu prüfen, ob Sie dies richtig durchgeführt haben.
Schritt 3: Bindungsobjekt in der Hauptaktivität erstellen
Fügen Sie der Hauptaktivität einen Verweis auf das Bindungsobjekt hinzu, damit Sie damit auf Ansichten zugreifen können:
- Öffnen Sie die Datei
MainActivity.kt
. - Erstellen Sie auf oberster Ebene vor
onCreate()
eine Variable für das Bindungsobjekt. Diese Variable wird normalerweise alsbinding
bezeichnet.
Der Typ vonbinding
, der KlasseActivityMainBinding
, wird vom Compiler speziell für diese Hauptaktivität erstellt. Der Name wird vom Namen der Layoutdatei (activity_main + Binding
) abgeleitet.
private lateinit var binding: ActivityMainBinding
- Importieren Sie
ActivityMainBinding
, wenn Sie von Android Studio dazu aufgefordert werden. Wenn Sie nicht aufgefordert werden, klicken Sie aufActivityMainBinding
und drücken SieAlt+Enter
(Option+Enter
auf einem Mac), um diesen fehlenden Kurs zu importieren. Weitere Tastenkombinationen finden Sie im Hilfeartikel Tastenkombinationen in der Admin-Konsole.
Die Anweisungimport
sollte der folgenden ähneln.
import com.example.android.aboutme.databinding.ActivityMainBinding
Ersetzen Sie dann die aktuelle setContentView()
-Funktion durch eine Anweisung, die Folgendes ausführt:
- Erstellt das Bindungsobjekt.
- Verwendet die Funktion
setContentView()
aus der KlasseDataBindingUtil
, um das Layoutactivity_main
mitMainActivity
zu verknüpfen. DiesesetContentView()
-Funktion übernimmt auch die Einrichtung der Datenbindung für die Datenansichten.
- Ersetzen Sie in
onCreate()
densetContentView()
-Aufruf durch die folgende Codezeile.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- Importieren Sie
DataBindingUtil
.
import androidx.databinding.DataBindingUtil
Schritt 4: Mit dem Bindungsobjekt alle Aufrufe von „findViewById()“ ersetzen
Sie können jetzt alle Aufrufe von findViewById()
durch Verweise auf die Ansichten im Bindungsobjekt ersetzen. Wenn das Bindungsobjekt erstellt wird, generiert der Compiler die Namen der Ansichten im Bindungsobjekt aus den IDs der Ansichten im Layout. Diese wandeln sie in die Camel-Case-Schreibweise um. Beispiel: done_button
ist im Bindungsobjekt doneButton
, nickname_edit
wird zu nicknameEdit
und nickname_text
zu nicknameText
.
- Ersetzen Sie in
onCreate()
den Code, derfindViewById()
verwendet, um dendone_button
zu finden, mit dem Code, der auf die Schaltfläche im Bindungsobjekt verweist.
Ersetze diesen Code:findViewById<Button>(R.id.
done_button
)
durch:binding.doneButton
Dein fertiger Code, um den Klick-Listener inonCreate()
festzulegen, sollte so aussehen.
binding.doneButton.setOnClickListener {
addNickname(it)
}
- Dasselbe gilt für alle Aufrufe von
findViewById()
in deraddNickname()
-Funktion.
Ersetzen Sie alle Vorkommen vonfindViewById<
View
>(R.id.
id_view
)
durchbinding.
idView
. Gehen Sie dazu so vor:
- Löschen Sie die Definitionen für die Variablen
editText
undnicknameTextView
sowie die zugehörigen Aufrufe anfindViewById()
. Dies führt zu Fehlern. - Behebe die Fehler, indem du die
nicknameText
-,nicknameEdit
- unddoneButton
-Ansichten aus denbinding
-Objekten statt der (gelöschten) Variablen erhältst. - Ersetzen Sie
view.visibility
durchbinding.doneButton.visibility
. Mit dem Codebinding.doneButton
anstelle des übergebenenview
wird der Code einheitlicher.
Das Ergebnis ist der folgende Code:
binding.nicknameText.text = binding.nicknameEdit.text
binding.nicknameEdit.visibility = View.GONE
binding.doneButton.visibility = View.GONE
binding.nicknameText.visibility = View.VISIBLE
- An den Funktionen ändert sich nichts. Optional kannst du den
view
-Parameter jetzt eliminieren und alle Verwendungen vonview
aktualisieren, umbinding.doneButton
in dieser Funktion zu verwenden.
- Für
nicknameText
ist eineString
und fürnicknameEdit.text
einEditable
erforderlich. Wenn Sie die Datenbindung verwenden, müssen Sie dieEditable
explizit in einString
konvertieren.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
- Sie können die ausgegrauten Importe löschen.
- Kotlin-Code der Funktion mithilfe von
apply{}
erstellen.
binding.apply {
nicknameText.text = nicknameEdit.text.toString()
nicknameEdit.visibility = View.GONE
doneButton.visibility = View.GONE
nicknameText.visibility = View.VISIBLE
}
- Erstelle deine App und führe sie aus...alles sollte genauso funktionieren wie vorher.
Mithilfe der Datenbindung können Sie eine Datenklasse direkt für eine Datenansicht verfügbar machen. Diese Technik vereinfacht den Code und ist äußerst nützlich für komplexere Fälle.
In diesem Beispiel erstellen Sie anstelle der Namen und Aliase mithilfe von String-Ressourcen eine Datenklasse für Name und Alias. Die Datenklasse wird mithilfe von Datenbindung für die Ansicht verfügbar.
Schritt 1: Datenklasse „MyName“ erstellen
- Öffnen Sie in Android Studio im Verzeichnis
java
die DateiMyName.kt
. Wenn Sie diese Datei nicht haben, erstellen Sie eine neue Kotlin-Datei und nennen Sie sieMyName.kt
. - Definieren Sie eine Datenklasse für Name und Alias. Verwenden Sie leere Strings als Standardwerte.
data class MyName(var name: String = "", var nickname: String = "")
Schritt 2: Dem Layout Daten hinzufügen
In der Datei activity_main.xml
wird der Name derzeit in einem TextView
aus einer String-Ressource festgelegt. Sie müssen den Verweis auf den Namen durch einen Verweis auf Daten in der Datenklasse ersetzen.
- Öffnen Sie
activity_main.xml
auf dem Tab Text. - Fügen Sie oben im Layout zwischen den Tags
<layout>
und<LinearLayout>
ein<data></data>
-Tag ein. Hier verbinden Sie die Ansicht mit den Daten.
<data>
</data>
In den Daten-Tags können Sie benannte Variablen angeben, die einen Verweis auf eine Klasse enthalten.
- Füge im Tag
<data>
ein<variable>
-Tag ein. - Fügen Sie einen
name
-Parameter hinzu, um der Variable den Namen"myName"
zu geben. Fügen Sie einentype
-Parameter hinzu und setzen Sie den Typ auf einen voll qualifizierten Namen der DatenklasseMyName
(Paketname + Variablenname).
<variable
name="myName"
type="com.example.android.aboutme.MyName" />
Anstatt auf die String-Ressource für den Namen zu verwenden, können Sie jetzt auf die Variable myName
verweisen.
- Ersetzen Sie
android:text="@string/name"
durch den folgenden Code.
@={}
ist eine Anweisung zum Abrufen der Daten, auf die in geschweiften Klammern verwiesen wird.
myName
verweist auf die zuvor definierte Variable myName
, die auf die Datenklasse myName
verweist und die name
-Property aus der Klasse abruft.
android:text="@={myName.name}"
Schritt 3: Daten erstellen
Sie haben jetzt einen Verweis auf die Daten in Ihrer Layoutdatei. Als Nächstes erstellen Sie die Daten.
- Öffnen Sie die Datei
MainActivity.kt
. - Erstellen Sie oberhalb von
onCreate()
eine private Variable, die per KonventionmyName
genannt wird. Weisen Sie der Variable eine Instanz der DatenklasseMyName
zu und übergeben Sie den Namen.
private val myName: MyName = MyName("Aleks Haecky")
- Lege in
onCreate()
den Wert der VariablenmyName
in der Layoutdatei auf den WertmyName
fest, den du gerade deklariert hast. Sie können in der XML nicht direkt auf die Variable zugreifen. Sie müssen über das Bindungsobjekt darauf zugreifen.
binding.myName = myName
- Dies kann einen Fehler anzeigen, da Sie das Bindungsobjekt nach Änderungen aktualisieren müssen. Erstellen Sie Ihre App, und der Fehler sollte nicht mehr auftreten.
Schritt 4: Die Datenklasse für den Alias in der TextView verwenden
Im letzten Schritt können Sie auch die Datenklasse für den Alias in der TextView
verwenden.
- Öffnen Sie
activity_main.xml
. - Füge in der Textansicht „
nickname_text
“ einetext
-Property hinzu. Verweisen Sie wie in der folgenden Abbildung beschrieben auf dienickname
in der Datenklasse.
android:text="@={myName.nickname}"
- Ersetzen Sie in
ActivityMain
nicknameText.text = nicknameEdit.text.toString()
durch Code, um den Alias in der VariablemyName
festzulegen.
myName?.nickname = nicknameEdit.text.toString()
Nachdem der Alias festgelegt wurde, möchten Sie, dass der Code die UI mit den neuen Daten aktualisiert. Dazu müssen Sie alle Bindungsausdrücke so entwerten, dass sie mit den richtigen Daten neu erstellt werden.
- Fügen Sie
invalidateAll()
hinzu, nachdem Sie den Alias festgelegt haben, damit die UI mit dem Wert im aktualisierten Bindungsobjekt aktualisiert wird.
binding.apply {
myName?.nickname = nicknameEdit.text.toString()
invalidateAll()
...
}
- Erstelle deine App und führe sie aus. Es sollte genauso funktionieren wie vorher.
Android Studio-Projekt: AboutMeDataBindung
So verwenden Sie die Datenbindung, um Aufrufe von findViewById()
zu ersetzen:
- Datenbindung im Android-Abschnitt der Datei
build.gradle
aktivieren:dataBinding { enabled = true }
- Verwende
<layout>
als Stammansicht in deinem XML-Layout. - Bindungsvariable definieren:
private lateinit var binding: ActivityMainBinding
- Bindungsobjekt in
MainActivity
erstellen undsetContentView
ersetzen:binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- Ersetzen Sie Aufrufe von
findViewById()
durch Verweise auf die Ansicht im Bindungsobjekt. Beispiel:findViewById<Button>(R.id.done_button) ⇒ binding.doneBu
tton
(Im Beispiel wird der Name der Ansicht aus der Kamel-Fälle aus der Ansichtid
in der XML-Datei generiert.)
So binden Sie Datenansichten an Daten:
- Erstellen Sie eine Datenklasse für Ihre Daten.
- Fügen Sie einen
<data>
-Block in das<layout>
-Tag ein. - Definieren Sie eine
<variable>
mit einem Namen und einem Typ, der die Datenklasse darstellt.
<data>
<variable
name="myName"
type="com.example.android.aboutme.MyName" />
</data>
- Erstellen Sie in
MainActivity
eine Variable mit einer Instanz der Datenklasse. Beispiel:private val myName: MyName = MyName("Aleks Haecky")
- Legen Sie im Bindungsobjekt die Variable auf, die Sie gerade erstellt haben:
binding.myName = myName
- Legen Sie in der XML den Inhalt der Ansicht auf die Variable fest, die Sie im Block
<data>
definiert haben. Verwenden Sie die Punktschreibweise, um auf die Daten in der Datenklasse zuzugreifen.android:text="@={myName.name}"
Udacity-Kurs:
Android-Entwicklerdokumentation:
In diesem Abschnitt werden mögliche Hausaufgaben für Schüler oder Studenten aufgeführt, die an diesem von einem Kursleiter geleiteten Codelab arbeiten. Die Lehrkraft kann Folgendes tun:
- Bei Bedarf können Sie die entsprechenden Aufgaben zuweisen.
- Schülern mitteilen, wie sie Aufgaben für die Aufgabe abgeben
- Benoten Sie die Hausaufgaben.
Lehrkräfte können diese Vorschläge so oft oder so oft verwenden, wie sie möchten. anderen Aufgaben können sie nach Belieben zugewiesen werden.
Wenn Sie alleine an diesem Codelab arbeiten, können Sie Ihr Wissen mit diesen Hausaufgaben testen.
Diese Fragen beantworten
Frage 1
Warum möchten Sie explizite und implizite Aufrufe von findViewById()
minimieren?
- Bei jedem Aufruf von
findViewById()
wird die Ansichtshierarchie durchlaufen. findViewById()
wird im Haupt- oder UI-Thread ausgeführt.- Diese Aufrufe können die Benutzeroberfläche verlangsamen.
- Deine App stürzt seltener ab.
Frage 2
Wie würden Sie die Datenbindung beschreiben?
Hier sind einige Beispiele, die Sie zur Datenbindung sagen könnten:
- Die große Idee der Datenbindung besteht darin, ein Objekt zu erstellen, das bei der Kompilierung zwei Teile weit entfernter Informationen miteinander verbindet, verknüpft oder verbindet, sodass Sie zur Laufzeit nicht auf die Daten achten müssen.
- Das Objekt, das diese Bindungen anzeigt, wird als Bindungsobjekt bezeichnet.
- Das Bindungsobjekt wird vom Compiler erstellt.
Frage 3
Welche der folgenden Maßnahmen ist KEINE Vorteile der Datenbindung?
- Der Code ist kürzer, leichter zu lesen und leichter zu verwalten.
- Daten und Datenansichten sind deutlich voneinander getrennt.
- Das Android-System durchlaufen die Ansichtshierarchie nur einmal, um jede Datenansicht abzurufen.
- Durch den Aufruf von
findViewById()
wird ein Compiler-Fehler generiert. - Geben Sie die Sicherheit für den Zugriff auf Datenansichten ein.
Frage 4
Welche Funktion hat das <layout>
-Tag?
- Sie müssen es um das Stammverzeichnis im Layout ziehen.
- Bindungen werden für alle Ansichten in einem Layout erstellt.
- Die Ansicht der obersten Ebene wird in einem XML-Layout festgelegt, für das die Datenbindung verwendet wird.
- Sie können das
<data>
-Tag in einem<layout>
verwenden, um eine Variable an eine Datenklasse zu binden.
Frage 5
Wie verweise ich auf gebundene Daten im XML-Layout?
android:text="@={myDataClass.property}"
android:text="@={myDataClass}"
android:text="@={myDataClass.property.toString()}"
android:text="@={myDataClass.bound_data.property}"
Mit der nächsten Lektion beginnen:
Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage zu Kotlin-Grundlagen für Android.