Android Kotlin Fundamentals 0.4: Datenbindung – Grundlagen

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.

  1. 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.
  2. Öffnen Sie die Datei build.gradle (Module: app).
  3. Fügen Sie innerhalb des Abschnitts android vor der schließenden geschweiften Klammer einen dataBinding-Abschnitt ein und setzen Sie enabled auf true.
dataBinding {
    enabled = true
}
  1. 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.
  2. 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.

  1. Öffnen Sie die Datei activity_main.xml.
  2. Wechseln Sie zum Tab Text.
  3. Fügen Sie <layout></layout> als äußerstes Tag um <LinearLayout> hinzu.
<layout>
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>
  1. 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.
  1. 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">
  1. 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:

  1. Öffnen Sie die Datei MainActivity.kt.
  2. Erstellen Sie auf oberster Ebene vor onCreate() eine Variable für das Bindungsobjekt. Diese Variable wird normalerweise als binding bezeichnet.

    Der Typ von binding, der Klasse ActivityMainBinding, 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
  1. Importieren Sie ActivityMainBinding, wenn Sie von Android Studio dazu aufgefordert werden. Wenn Sie nicht aufgefordert werden, klicken Sie auf ActivityMainBinding und drücken Sie Alt+Enter (Option+Enter auf einem Mac), um diesen fehlenden Kurs zu importieren. Weitere Tastenkombinationen finden Sie im Hilfeartikel Tastenkombinationen in der Admin-Konsole.

    Die Anweisung import 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 Klasse DataBindingUtil, um das Layout activity_main mit MainActivity zu verknüpfen. Diese setContentView()-Funktion übernimmt auch die Einrichtung der Datenbindung für die Datenansichten.
  1. Ersetzen Sie in onCreate() den setContentView()-Aufruf durch die folgende Codezeile.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  1. 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.

  1. Ersetzen Sie in onCreate() den Code, der findViewById() verwendet, um den done_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 in onCreate() festzulegen, sollte so aussehen.
binding.doneButton.setOnClickListener {
   addNickname(it)
}
  1. Dasselbe gilt für alle Aufrufe von findViewById() in der addNickname()-Funktion.
    Ersetzen Sie alle Vorkommen von findViewById<View>(R.id.id_view) durch binding.idView. Gehen Sie dazu so vor:
  • Löschen Sie die Definitionen für die Variablen editText und nicknameTextView sowie die zugehörigen Aufrufe an findViewById(). Dies führt zu Fehlern.
  • Behebe die Fehler, indem du die nicknameText-, nicknameEdit- und doneButton-Ansichten aus den binding-Objekten statt der (gelöschten) Variablen erhältst.
  • Ersetzen Sie view.visibility durch binding.doneButton.visibility. Mit dem Code binding.doneButton anstelle des übergebenen view 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 von view aktualisieren, um binding.doneButton in dieser Funktion zu verwenden.
  1. Für nicknameText ist eine String und für nicknameEdit.text ein Editable erforderlich. Wenn Sie die Datenbindung verwenden, müssen Sie die Editable explizit in ein String konvertieren.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
  1. Sie können die ausgegrauten Importe löschen.
  2. 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
}
  1. 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

  1. Öffnen Sie in Android Studio im Verzeichnis java die Datei MyName.kt. Wenn Sie diese Datei nicht haben, erstellen Sie eine neue Kotlin-Datei und nennen Sie sie MyName.kt.
  2. 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.

  1. Öffnen Sie activity_main.xml auf dem Tab Text.
  2. 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.

  1. Füge im Tag <data> ein <variable>-Tag ein.
  2. Fügen Sie einen name-Parameter hinzu, um der Variable den Namen "myName" zu geben. Fügen Sie einen type-Parameter hinzu und setzen Sie den Typ auf einen voll qualifizierten Namen der Datenklasse MyName (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.

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

  1. Öffnen Sie die Datei MainActivity.kt.
  2. Erstellen Sie oberhalb von onCreate() eine private Variable, die per Konvention myName genannt wird. Weisen Sie der Variable eine Instanz der Datenklasse MyName zu und übergeben Sie den Namen.
private val myName: MyName = MyName("Aleks Haecky")
  1. Lege in onCreate() den Wert der Variablen myName in der Layoutdatei auf den Wert myName 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
  1. 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.

  1. Öffnen Sie activity_main.xml.
  2. Füge in der Textansicht „nickname_text“ eine text-Property hinzu. Verweisen Sie wie in der folgenden Abbildung beschrieben auf die nickname in der Datenklasse.
android:text="@={myName.nickname}"
  1. Ersetzen Sie in ActivityMain
    nicknameText.text = nicknameEdit.text.toString()
    durch Code, um den Alias in der Variable myName 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.

  1. 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()
   ...
}
  1. 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:

  1. Datenbindung im Android-Abschnitt der Datei build.gradle aktivieren:
    dataBinding { enabled = true }
  2. Verwende <layout> als Stammansicht in deinem XML-Layout.
  3. Bindungsvariable definieren:
    private lateinit var binding: ActivityMainBinding
  4. Bindungsobjekt in MainActivity erstellen und setContentView ersetzen:
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  5. Ersetzen Sie Aufrufe von findViewById() durch Verweise auf die Ansicht im Bindungsobjekt. Beispiel:
    findViewById<Button>(R.id.done_button) ⇒ binding.doneButton
    (Im Beispiel wird der Name der Ansicht aus der Kamel-Fälle aus der Ansicht id in der XML-Datei generiert.)

So binden Sie Datenansichten an Daten:

  1. Erstellen Sie eine Datenklasse für Ihre Daten.
  2. Fügen Sie einen <data>-Block in das <layout>-Tag ein.
  3. 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>
  1. Erstellen Sie in MainActivity eine Variable mit einer Instanz der Datenklasse. Beispiel:
    private val myName: MyName = MyName("Aleks Haecky")
  1. Legen Sie im Bindungsobjekt die Variable auf, die Sie gerade erstellt haben:
    binding.myName = myName
  1. 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: 3.1: Fragment erstellen

Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage zu Kotlin-Grundlagen für Android.