Android Kotlin Fundamentals 07.2: DiffUtil und Datenbindung mit RecyclerView

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

Im vorherigen Codelab hast du die TrackMySleepquality-App aktualisiert, sodass Daten zur Schlafqualität in einem RecyclerView angezeigt werden. Die Techniken, die Sie bei der Erstellung Ihrer ersten RecyclerView gelernt haben, reichen für die meisten RecyclerViews aus, die einfache Listen zeigen, die nicht zu groß sind. Allerdings gibt es eine Reihe von Techniken, die RecyclerView für große Listen effizienter machen und Ihren Code einfacher für die Pflege und Erweiterung komplexer Listen und Raster erleichtern.

In diesem Codelab baust du auf der Schlaf-Tracker-App aus dem vorherigen Codelab auf. Sie lernen, die Liste der Schlafdaten effektiver zu aktualisieren und lernen, wie man die Datenbindung mit RecyclerView nutzt. Wenn Sie die App aus dem vorherigen Codelab nicht haben, können Sie den Startcode für dieses Codelab herunterladen.

Was Sie bereits wissen sollten

  • Erstellen einer einfachen Benutzeroberfläche mit einer Aktivität, Fragmenten und Ansichten.
  • Die Navigation zwischen den Fragmenten und die Verwendung von safeArgs zum Übergeben von Daten zwischen Fragmenten.
  • Modelle ansehen, Modellfabriken, Transformationen und LiveData und ihre Betrachter ansehen.
  • Erstellen einer Room-Datenbank, eines DAO und Definieren von Entitäten.
  • Koroutinen für Datenbanken und andere langlebige Aufgaben verwenden
  • Einfache RecyclerView mit einem Adapter-, ViewHolder- und Elementlayout implementieren

Lerninhalte

  • Mit DiffUtil kannst du eine von RecyclerView angezeigte Liste effizient aktualisieren.
  • So verwenden Sie die Datenbindung mit RecyclerView.
  • Bindungsadapter für die Transformation von Daten verwenden

Aufgaben

  • baue auf die TrackMySleepquality-App des vorherigen Codelabs in dieser Serie auf.
  • Aktualisiere die SleepNightAdapter, um die Liste mit DiffUtil effizient zu aktualisieren.
  • Implementiere die Datenbindung für die RecyclerView mithilfe von Bindungsadaptern, um die Daten zu transformieren.

Die Schlaf-Tracker-App hat zwei Bildschirme, die als Fragmente dargestellt sind (siehe Abbildung unten).

Auf dem ersten Bildschirm auf der linken Seite finden Sie Schaltflächen zum Starten und Beenden der Aufzeichnung. Auf dem Bildschirm werden einige Schlafdaten des Nutzers angezeigt. Mit der Schaltfläche Löschen werden alle Daten gelöscht, die die App für den Nutzer erfasst hat. Auf dem zweiten Bildschirm rechts wird die Qualität des Schlafs angezeigt.

Diese App ist so konzipiert, dass sie einen UI-Controller, ViewModel und LiveData sowie eine Room-Datenbank verwendet, um Schlafdaten zu speichern.

Die Schlafdaten werden in RecyclerView angezeigt. In diesem Codelab erstellen Sie DiffUtil und die Datenbindung für RecyclerView. Nach diesem Codelab wird Ihre App genau gleich aussehen, aber sie ist effizienter und einfacher zu verwalten und zu verwalten.

Sie können die SleepTracker-App aus dem vorherigen Codelab weiterhin verwenden oder die RecyclerViewDiffUtilDataData-Starter App von GitHub herunterladen.

  1. Laden Sie bei Bedarf die RecyclerViewDiffUtilDataBindung-Starter-App von GitHub herunter und öffnen Sie das Projekt in Android Studio.
  2. Führen Sie die App aus.
  3. Öffnen Sie die Datei SleepNightAdapter.kt.
  4. Prüfen Sie den Code, um sich mit der Struktur der App vertraut zu machen. Unten sehen Sie eine Zusammenfassung der Verwendung von RecyclerView mit dem Adaptermuster zur Darstellung von Schlafdaten für den Nutzer.

  • Anhand der Nutzereingabe erstellt die App eine Liste von SleepNight-Objekten. Jedes SleepNight-Objekt repräsentiert eine einzelne Nacht, die Dauer und die Qualität des Schlafs.
  • Mit dem SleepNightAdapter wird die Liste der SleepNight-Objekte in etwas angepasst, das RecyclerView verwenden und anzeigen kann.
  • Mit dem Adapter SleepNightAdapter werden ViewHolders generiert. Diese enthalten die Ansichten, Daten und Metainformationen für die Recycler-Ansicht, die die Daten darstellen.
  • RecyclerView verwendet SleepNightAdapter, um zu bestimmen, wie viele Elemente angezeigt werden können (getItemCount()). RecyclerView verwendet onCreateViewHolder() und onBindViewHolder(), um Aufrufhalter an Daten zur Anzeige zu binden.

Die Parameter „unDataDataSetChanged()“ ist ineffizient

Damit RecyclerView informiert wird, dass sich ein Element in der Liste geändert hat und aktualisiert werden muss, wird mit dem aktuellen Code notifyDataSetChanged() in SleepNightAdapter aufgerufen (siehe unten).

var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

notifyDataSetChanged() teilt RecyclerView jedoch mit, dass die gesamte Liste möglicherweise ungültig ist. Deshalb wird RecyclerView jedes Element in der Liste noch einmal neu verknüpfen, auch nicht auf dem Bildschirm sichtbar. Das ist sehr viel Arbeit. Bei umfangreichen oder komplexen Listen kann es einige Zeit dauern, bis das Display flackert oder ruckelt, wenn der Nutzer durch die Liste scrollt.

Um das Problem zu beheben, kannst du RecyclerView genau mitteilen, was sich geändert hat. RecyclerView kann dann nur die Ansichten aktualisieren, die sich auf dem Bildschirm geändert haben.

RecyclerView hat eine umfangreiche API zum Aktualisieren eines einzelnen Elements. Mit notifyItemChanged() kannst du RecyclerView mitteilen, dass sich ein Element geändert hat, und ähnliche Funktionen für Elemente verwenden, die hinzugefügt, entfernt oder verschoben wurden. Sie können das alles manuell erledigen, aber die Aufgabe ist nicht schwierig und kann ziemlich viel Code beinhalten.

Zum Glück gibt es die bessere Möglichkeit.

DiffUtil ist effizient und übernimmt die Arbeit für Sie

RecyclerView hat eine Klasse namens DiffUtil, mit der die Unterschiede zwischen zwei Listen berechnet werden. DiffUtil verwendet eine alte Liste und eine neue Liste und ermittelt die Unterschiede. Elemente, die hinzugefügt, entfernt oder geändert wurden, werden gefunden. Dann verwendet es einen Algorithmus namens Eugene W. Der Algorithmus von Myersstellt die Mindestanzahl von Änderungen fest, die von der alten Liste vorgenommen werden müssen, um die neue Liste zu generieren.

Sobald DiffUtil herausgefunden hat, was sich geändert hat, kann RecyclerView diese Informationen verwenden, um nur die Elemente zu aktualisieren, die hinzugefügt, entfernt oder verschoben wurden. Das ist wesentlich effizienter als das Wiederholen der gesamten Liste.

In dieser Aufgabe führen Sie ein Upgrade von SleepNightAdapter durch, um DiffUtil zu verwenden, um RecyclerView für Datenänderungen zu optimieren.

Schritt 1: SleepNightDiffCallback implementieren

Erweitere DiffUtil.ItemCallback, um die Funktionalität der DiffUtil-Klasse zu nutzen.

  1. Öffnen Sie SleepNightAdapter.kt.
  2. Erstellen Sie unterhalb der vollständigen Klassendefinition für SleepNightAdapter eine neue übergeordnete Klasse namens SleepNightDiffCallback, die DiffUtil.ItemCallback erweitert. Übergib SleepNight als generischen Parameter.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
  1. Fügen Sie den Cursor in den Klassennamen SleepNightDiffCallback ein.
  2. Drücken Sie Alt+Enter (Option+Enter auf dem Mac) und wählen Sie Mitglieder implementieren aus.
  3. Ein Dialogfeld wird geöffnet. Klicken Sie mit der linken Maustaste, um die Methoden areItemsTheSame() und areContentsTheSame() auszuwählen, und klicken Sie dann auf OK.

    Damit werden für die beiden Methoden Stubs in SleepNightDiffCallback generiert, wie unten dargestellt. DiffUtil verwendet diese beiden Methoden, um herauszufinden, wie sich die Liste und die Artikel verändert haben.
    override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
  1. Ersetzen Sie TODO in areItemsTheSame() durch Code, der prüft, ob die beiden übergebenen SleepNight-Elemente oldItem und newItem identisch sind. Wenn die Artikel denselben nightId haben, handelt es sich um denselben Artikel. Geben Sie true zurück. Andernfalls wird false zurückgegeben. DiffUtil verwendet diesen Test, um festzustellen, ob ein Element hinzugefügt, entfernt oder verschoben wurde.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem.nightId == newItem.nightId
}
  1. Prüfen Sie, ob oldItem und newItem in areContentsTheSame() dieselben Daten enthalten. Diese Gleichheitsüberprüfung prüft alle Felder, da SleepNight eine Datenklasse ist. Mit Data-Klassen werden equals und einige andere Methoden automatisch definiert. Wenn es Unterschiede zwischen oldItem und newItem gibt, informiert dieser Code DiffUtil darüber, dass das Element aktualisiert wurde.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem == newItem
}

Es ist ein gängiges Muster, ein RecyclerView zur Anzeige einer sich ändernden Liste zu verwenden. RecyclerView stellt die Adapterklasse ListAdapter bereit, mit der Sie einen RecyclerView-Adapter erstellen können, der von einer Liste unterstützt wird.

ListAdapter erfasst die Liste und informiert den Adapter bei der Aktualisierung.

Schritt 1: Adapter ändern, um ListAdapter zu erweitern

  1. Ändern Sie in der Datei SleepNightAdapter.kt die Klassensignatur von SleepNightAdapter, um ListAdapter zu erweitern.
  2. Importieren Sie den androidx.recyclerview.widget.ListAdapter, wenn Sie dazu aufgefordert werden.
  3. Fügen Sie SleepNight als erstes Argument vor ListAdapter hinzu (vor SleepNightAdapter.ViewHolder).
  4. Fügen Sie SleepNightDiffCallback() als Parameter zum Konstruktor hinzu. Das ListAdapter verwendet dieses Feld, um herauszufinden, was sich in der Liste geändert hat. Die fertige SleepNightAdapter-Unterschrift sollte so aussehen:
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. Löschen Sie innerhalb der Klasse SleepNightAdapter das Feld data, einschließlich des Setters. Du brauchst sie nicht mehr, weil ListAdapter die Liste für dich verwaltet.
  2. Lösche die Überschreibung von getItemCount(), da ListAdapter diese Methode für dich implementiert.
  3. Ändern Sie die Variable item, um den Fehler in onBindViewHolder() zu entfernen. Anstatt data zu erhalten, rufen Sie eine item-Methode auf, die von ListAdapter bereitgestellt wird.
val item = getItem(position)

Schritt 2: Liste mit „listList()“ aktualisieren

Der Code muss ListAdapter mitteilen, wenn eine geänderte Liste verfügbar ist. ListAdapter bietet eine Methode namens submitList(), mit der ListAdapter informiert wird, dass eine neue Version der Liste verfügbar ist. Beim Aufrufen dieser Methode vergleicht ListAdapter die neue Liste mit der alten Liste und erkennt Elemente, die hinzugefügt, entfernt, verschoben oder geändert wurden. Anschließend werden durch ListAdapter die von RecyclerView angezeigten Elemente aktualisiert.

  1. Öffnen Sie SleepTrackerFragment.kt.
  2. Suchen Sie im onCreateView() im Beobachtungsserver unter sleepTrackerViewModel nach dem Fehler, auf den die gelöschte data-Variable verweist.
  3. Ersetzen Sie adapter.data = it durch einen Aufruf von adapter.submitList(it). Der aktualisierte Code wird unten dargestellt.

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.submitList(it)
   }
})
  1. Führe deine App aus. Sie wird schneller ausgeführt, wenn deine Liste klein ist.

Bei dieser Aufgabe verwenden Sie dasselbe Verfahren wie in vorherigen Codelabs, um die Datenbindung einzurichten. Außerdem vermeiden Sie Aufrufe von findViewById().

Schritt 1: Datenbindung zur Layoutdatei hinzufügen

  1. Öffne die Layoutdatei list_item_sleep_night.xml auf dem Tab Text.
  2. Setze den Cursor auf das Tag ConstraintLayout und drücke Alt+Enter (Option+Enter auf einem Mac). Das Intent-Menü (das Schnellmenü) wird geöffnet.
  3. Wählen Sie In Datenbindungslayout konvertieren aus. Dadurch wird das Layout in <layout> eingeschlossen und darin wird ein <data>-Tag eingefügt.
  4. Scrollen Sie bei Bedarf zurück nach oben und definieren Sie im <data>-Tag eine Variable mit dem Namen sleep.
  5. Machen Sie seinen type zum voll qualifizierten Namen von SleepNight, com.example.android.trackmysleepquality.database.SleepNight. Das fertige <data>-Tag sollte wie unten gezeigt aussehen.
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Wenn Sie die Erstellung des Objekts Binding erzwingen möchten, wählen Sie Build > Clean Project und dann Build > Rebuild Project aus. Falls weiterhin Probleme auftreten, wählen Sie Datei > Caches entwerten/Neu starten aus. Das Bindungsobjekt ListItemSleepNightBinding sowie der zugehörige Code werden den generierten Dateien des Projekts hinzugefügt.

Schritt 2: Artikellayout mithilfe von Datenbindung erweitern

  1. Öffnen Sie SleepNightAdapter.kt.
  2. Suche in der Klasse ViewHolder nach der Methode from().
  3. Löschen Sie die Deklaration der Variable view.

Code zum Löschen:

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. Legen Sie dort, wo die view-Variable war, eine neue Variable mit dem Namen binding fest, die das Bindungsobjekt ListItemSleepNightBinding aufgebläht. Führen Sie den erforderlichen Import des Bindungsobjekts aus.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. Geben Sie am Ende der Funktion binding zurück, anstatt view zurückzugeben.
return ViewHolder(binding)
  1. Fügen Sie den Cursor über das Wort binding, um den Fehler zu beheben. Drücken Sie Alt+Enter (Option+Enter auf einem Mac), um das Intent-Menü zu öffnen.
  1. Wählen Sie Parameter „'itemView'“ des primären Konstruktors der Klasse „'ViewHolder'“ auf 'ListItemSleepNightBindung' aus. Aktualisiert den Parametertyp der Klasse ViewHolder.

  1. Scrollen Sie nach oben zur Klassendefinition von ViewHolder, um die Änderung in der Signatur zu sehen. Sie sehen eine Fehlermeldung für itemView, weil Sie itemView in from() in der Methode from() geändert haben.

    Klicken Sie in der Klassendefinition ViewHolder mit der rechten Maustaste auf eine der Vorkommen in itemView und wählen Sie Refaktorieren > Umbenennen aus. Ändern Sie den Namen in binding.
  2. Stelle dem Konstruktor-Parameter binding val zu, um sie als Property festzulegen.
  3. Ändern Sie beim Aufruf der übergeordneten Klasse RecyclerView.ViewHolder den Parameter von binding in binding.root. Sie müssen eine View übergeben. binding.root ist die Stamm-ConstraintLayout in Ihrem Artikellayout.
  4. Die fertige Kursdeklaration sollte so aussehen:
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

Außerdem wird eine Fehlermeldung für die Aufrufe von findViewById() angezeigt. Dieses Problem müssen Sie als Nächstes beheben.

Schritt 3: „findViewById()“ ersetzen

Du kannst jetzt die Properties sleepLength, quality und qualityImage aktualisieren, um das Objekt binding anstelle von findViewById() zu verwenden.

  1. Ändere die Initialisierungen von sleepLength, qualityString und qualityImage, um die Ansichten des binding-Objekts zu verwenden, wie unten dargestellt. Danach sollten keine Fehler mehr im Code angezeigt werden.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

Wenn das Bindungsobjekt vorhanden ist, müssen Sie die Properties sleepLength, quality und qualityImage nicht mehr definieren. DataBinding speichert die Lookups im Cache. Daher müssen diese Properties nicht deklariert werden.

  1. Klicken Sie mit der rechten Maustaste auf die Namen von Properties sleepLength, quality und qualityImage. Wählen Sie Refaktorieren &enden; Inline aus oder drücken Sie Control+Command+N (Option+Command+N auf dem Mac).
  2. Führen Sie die Anwendung aus. Möglicherweise müssen Sie das Projekt bereinigen und gegebenenfalls neu erstellen.

In dieser Aufgabe führen Sie ein Upgrade Ihrer App für die Datenbindung mit Bindungsadaptern aus, um die Daten in Ihren Ansichten festzulegen.

In einem vorherigen Codelab haben Sie die Klasse Transformations verwendet, um LiveData zu erstellen und formatierte Strings zu generieren, die in Textansichten angezeigt werden. Wenn Sie jedoch verschiedene Typen oder komplexe Typen binden müssen, können Sie Bindungsadapter bereitstellen, um die Datenbindung bei der Verwendung dieser Typen zu unterstützen. Bindungsadapter sind Adapter, die Ihre Daten so anpassen, dass sie mithilfe der Datenbindung eine Ansicht, z. B. Text oder ein Bild, binden können.

Sie implementieren drei Bindungsadapter, einen für das Bild und einen für jedes Textfeld. Definieren Sie dazu einen Bindungsadapter: Sie definieren eine Methode, die ein Element und eine Ansicht verwendet und mit @BindingAdapter annotiert. Im Text der Methode implementieren Sie die Transformation. In Kotlin können Sie einen Bindungsadapter als Erweiterungsfunktion in die Ansichtsklasse schreiben, die die Daten empfängt.

Schritt 1: Bindungsadapter erstellen

Beachten Sie, dass Sie in diesem Schritt mehrere Kurse importieren müssen, die nicht einzeln aufgerufen werden.

  1. Öffnen Sie SleepNightAdapater.kt.
  2. Suchen Sie in der Klasse ViewHolder die Methode bind() und erinnern Sie sich daran, was diese Methode bewirkt. Sie nehmen stattdessen den Code, der die Werte für binding.sleepLength, binding.quality und binding.qualityImage berechnet, und verwenden ihn im Adapter. Wir empfehlen, den Code vorerst unverändert zu lassen.
  3. Erstellen und öffnen Sie im Paket sleeptracker eine Datei mit dem Namen BindingUtils.kt.
  4. Deklarieren Sie in TextView die Erweiterungsfunktion setSleepDurationFormatted und übergeben Sie SleepNight. Diese Funktion ist dein Adapter zum Berechnen und Formatieren der Schlafdauer.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
  1. Binden Sie die Daten im Anfragetext von setSleepDurationFormatted an die Ansicht wie in ViewHolder.bind(). Rufe convertDurationToFormatted() auf und lege dann text für TextView auf den formatierten Text fest. Weil dies eine Erweiterungsfunktion unter TextView ist, kannst du direkt auf die Property text zugreifen.
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
  1. Kennzeichnen Sie die Funktion mit @BindingAdapter, um die Datenbindung über diesen Bindungsadapter zu informieren.
  2. Diese Funktion ist der Adapter für das Attribut sleepDurationFormatted. Übergeben Sie daher sleepDurationFormatted als Argument an @BindingAdapter.
@BindingAdapter("sleepDurationFormatted")
  1. Mit dem zweiten Adapter wird die Schlafqualität basierend auf dem Wert in einem SleepNight-Objekt festgelegt. Erstelle eine Erweiterungsfunktion namens setSleepQualityString() auf TextView und übergib ein SleepNight-Element.
  2. Binden Sie die Daten im Anfragetext an die Ansicht in ViewHolder.bind() an. Rufen Sie convertNumericQualityToString auf und legen Sie den text fest.
  3. Funktion mit @BindingAdapter("sleepQualityString") annotieren
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
   text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
  1. Mit dem dritten Bindungsadapter wird das Bild in einer Bildansicht festgelegt. Erstellen Sie die Erweiterungsfunktion in ImageView, rufen Sie setSleepImage auf und verwenden Sie den Code aus ViewHolder.bind(), wie unten dargestellt.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
   setImageResource(when (item.sleepQuality) {
       0 -> R.drawable.ic_sleep_0
       1 -> R.drawable.ic_sleep_1
       2 -> R.drawable.ic_sleep_2
       3 -> R.drawable.ic_sleep_3
       4 -> R.drawable.ic_sleep_4
       5 -> R.drawable.ic_sleep_5
       else -> R.drawable.ic_sleep_active
   })
}

Schritt 2: SleepNightAdapter aktualisieren

  1. Öffnen Sie SleepNightAdapter.kt.
  2. Löschen Sie alles in der Methode bind(), da Sie jetzt die Datenbindung und die neuen Adapter verwenden können.
fun bind(item: SleepNight) {
}
  1. Weisen Sie item in bind() den Schlaf zu, da Sie das Bindungsobjekt über Ihr neues SleepNight-Element informieren müssen.
binding.sleep = item
  1. Fügen Sie unter dieser Zeile binding.executePendingBindings() hinzu. Dieser Aufruf ist eine Optimierung, bei der die Datenbindung aufgefordert wird, alle ausstehenden Bindungen sofort auszuführen. Es wird immer empfohlen, executePendingBindings() aufzurufen, wenn Sie Bindungsadapter in einem RecyclerView-Element verwenden. Dies kann die Größe der Aufrufe leicht beschleunigen.
 binding.executePendingBindings()

Schritt 3: Bindungen zum XML-Layout hinzufügen

  1. Öffnen Sie list_item_sleep_night.xml.
  2. Fügen Sie in ImageView eine app-Property mit demselben Namen wie der Bindungsadapter hinzu, mit dem das Bild festgelegt wird. Übergeben Sie die Variable sleep wie unten gezeigt.

    Diese Property erstellt die Verbindung zwischen der Ansicht und dem Bindungsobjekt über den Adapter. Wenn auf sleepImage verwiesen wird, werden die Daten von SleepNight vom Adapter angepasst.
app:sleepImage="@{sleep}"
  1. Verfahren Sie ebenso mit den Textansichten "sleep_length" und "quality_string". Wenn sleepDurationFormatted oder sleepQualityString referenziert werden, passen die Adapter die Daten von SleepNight an.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
  1. Führen Sie Ihre App aus. Sie funktioniert genau wie vorher. Die Bindungsadapter übernehmen die Formatierung und die Aktualisierung von Ansichten, wenn sich die Daten ändern. Dadurch wird ViewHolder vereinfacht und der Code wesentlich besser strukturiert als zuvor.

Du hast für die letzten paar Übungen dieselbe Liste angezeigt. Wir zeigen Ihnen, dass Sie mit der Adapter-Oberfläche Ihren Code auf unterschiedliche Weise erstellen können. Je komplexer Ihr Code, desto wichtiger wird es, ihn zu entwerfen. In Produktions-Apps werden diese und andere Muster mit RecyclerView verwendet. Alle Muster funktionieren und jedes hat seine Vorteile. Für welche Sie sich entscheiden, hängt davon ab, was Sie erstellen.

Glückwunsch! Bist du auf dem richtigen Weg, dein Wissen über RecyclerView auf Android zu beherrschen?

Android Studio-Projekt: RecyclerViewDiffUtilDataBindung

DiffUtil:

  • RecyclerView hat eine Klasse namens DiffUtil, mit der die Unterschiede zwischen zwei Listen berechnet werden.
  • DiffUtil hat eine Klasse namens ItemCallBack, die Sie verlängern, um den Unterschied zwischen den beiden Listen zu ermitteln.
  • In der Klasse ItemCallback musst du die Methoden areItemsTheSame() und areContentsTheSame() überschreiben.

ListAdapter:

  • Wenn Sie Listen kostenlos verwalten möchten, verwenden Sie die Klasse ListAdapter anstelle von RecyclerView.Adapter. Wenn Sie ListAdapter verwenden, müssen Sie jedoch Ihren eigenen Adapter für andere Layouts erstellen. In diesem Codelab erfahren Sie, wie das geht.
  • Wenn Sie das Intent-Menü in Android Studio öffnen möchten, platzieren Sie den Cursor auf einem Code-Element und drücken Sie Alt+Enter (Option+Enter auf dem Mac). Dieses Menü ist besonders nützlich für die Refaktorierung von Code und die Erstellung von Stubs für Implementierungsmethoden. Das Menü ist kontextabhängig. Sie müssen den Cursor also genau platzieren, um das richtige Menü zu erhalten.

Datenbindung:

  • Datenbindung im Elementlayout verwenden, um Daten an die Ansichten zu binden.

Bindungsadapter:

  • Du hast zuvor Transformations verwendet, um Strings aus Daten zu erstellen. Wenn Sie Daten verschiedener oder komplexer Typen binden müssen, stellen Sie Bindungsadapter bereit, um die Datenbindung zu verwenden.
  • Wenn Sie einen Bindungsadapter deklarieren möchten, müssen Sie eine Methode definieren, die ein Element und eine Ansicht verwendet und mit @BindingAdapter die Annotation annotiert. In Kotlin können Sie den Bindungsadapter als Erweiterungsfunktion im View schreiben. Geben Sie den Namen der Eigenschaft ein, die der Adapter anpasst. Beispiel:
@BindingAdapter("sleepDurationFormatted")
  • Legen Sie im XML-Layout eine app-Property mit demselben Namen wie der Bindungsadapter fest. eine Variable mit den Daten übergeben. Beispiel:
.app:sleepDurationFormatted="@{sleep}"

Udacity-Kurse:

Android-Entwicklerdokumentation:

Weitere Informationen:

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

Was benötigen Sie, um DiffUtil verwenden zu können? Wählen Sie alle zutreffenden Antworten aus.

▢ Erweitern Sie die ItemCallBack-Klasse.

▢ Überschreibe areItemsTheSame().

▢ Überschreibe areContentsTheSame().

▢ Mit Datenbindung lassen sich die Unterschiede zwischen einzelnen Elementen verfolgen.

Frage 2

Welche der folgenden Aussagen über Bindungsadapter sind richtig?

▢ Ein Bindungsadapter ist eine Funktion, die mit @BindingAdapter kommentiert wird.

▢ Mit einem Bindungsadapter können Sie die Datenformatierung vom Inhaber der Ansicht trennen.

▢ Sie müssen ein RecyclerViewAdapter-Element verwenden, wenn Sie Bindungsadapter verwenden möchten.

▢ Bindungsadapter sind eine gute Lösung, wenn Sie komplexe Daten umwandeln müssen.

Frage 3

Wann sollten Sie Transformations anstelle eines Bindungsadapters verwenden? Wählen Sie alle zutreffenden Antworten aus.

▢.

▢ Sie formatieren einen String.

▢ Ihre Liste ist sehr lang.

▢ Der Messwert"ViewHolder"enthält nur einen Aufruf.

Beginnen Sie mit der nächsten Lektion: 7.3: GitterLayout mit RecyclerView