Android RecyclerView: Was ist, lernen Sie anhand einfacher Beispiele

⚡ Intelligente Zusammenfassung

RecyclerView ist ein fortschrittliches Android Dieses Widget stellt große, scrollbare Datensätze effizient dar, indem es eine begrenzte Anzahl von Ansichten wiederverwendet. Es nutzt einen Adapter, einen Layout-Manager und einen View-Holder, um Datensammlungen zu binden, die sich zur Laufzeit ändern.

  • 📱 Was es ist: RecyclerView ist ein flexibler Nachfolger von ListView und GridView zur Darstellung großer Datensammlungen.
  • 🧱 Ansichten und Ansichtsgruppen: Android Die Benutzeroberfläche wird mithilfe der Klassen View und ViewGroup gezeichnet, wobei LayoutParams Größe und Position steuert.
  • 🔄 Adapter: Das Adapter-Muster wandelt ein Datenarray in ViewHolder um, die vom RecyclerView akzeptiert werden können.
  • 📐 LayoutManager: Der Layout-Manager ordnet Elemente linear oder in einem Raster an und signalisiert, wann Ansichten wiederverwendet werden können.
  • ♻️ Recycling: Ansichten, die außerhalb des Bildschirms liegen, werden wiederverwendet statt neu erstellt. Das spart Speicherplatz und sorgt für ein flüssiges Scrollen.
  • ️ Bauschritte: Fügen Sie Gradle Abhängigkeiten erstellen: ein Elementlayout, einen ViewHolder, einen Adapter und einen LayoutManager.

Android RecyclerView

Was ist RecyclerView? Android?

Das RecyclerView Der RecyclerView ist eine flexiblere und fortschrittlichere Version von GridView und ListView. Er dient als Container zur Darstellung großer Datensätze, die durch die Verwaltung einer begrenzten Anzahl von Ansichten effizient gescrollt werden können. Sie können den RecyclerView verwenden, wenn Ihre Datensammlungen sich zur Laufzeit in Abhängigkeit von Netzwerkereignissen oder Benutzeraktionen ändern.

Aufrufe

Das Android Die Plattform verwendet die Klassen View und ViewGroup, um Elemente auf dem Bildschirm darzustellen. Diese Klassen sind absolut.tracDie Klassen `t` und `editText` werden je nach Anwendungsfall auf verschiedene Implementierungen erweitert. `TextView` dient beispielsweise lediglich der Anzeige von Textinhalten auf dem Bildschirm. `EditText` hingegen erbt von derselben `View`-Klasse und bietet zusätzliche Funktionen zur Dateneingabe.

Es ist möglich, eigene benutzerdefinierte Ansichten zu erstellen, um bei der Entwicklung mehr Flexibilität zu erreichen.ping Benutzeroberflächen. Die View-Klasse bietet Methoden, die wir überschreiben können, um auf dem Bildschirm zu zeichnen, sowie die Möglichkeit, Parameter wie Breite, Höhe und eigene Attribute zu übergeben, die wir unserer Ansicht hinzufügen möchten, um ihr das gewünschte Verhalten zu verleihen.

Ansichtsgruppen

Die Klasse `ViewGroup` ist eine Art von `View`, aber im Gegensatz zur einfachen `View`-Klasse, deren Aufgabe lediglich die Anzeige ist, ermöglicht `ViewGroup` das Zusammenfassen mehrerer Ansichten zu einer einzigen Ansicht, auf die wir als Ganzes zugreifen können. In diesem Fall wird die oberste Ansicht, der wir weitere einfache Ansichten hinzufügen, als „Elternansicht“ bezeichnet, und die darin enthaltenen Ansichten heißen „Kinderansichten“.

Wir können uns eine View als ein Array und eine ViewGroup als ein Array von Arrays vorstellen. Da ein Array von Arrays selbst wieder ein Array ist, lässt sich erkennen, wie eine ViewGroup wie eine View behandelt werden kann.

var arr1 = [1,2,3] //imagine a simple View as an Array
//we can imagine this as a NumberTextView which doesn't really exist
//but we could imagine there's one that makes it easy to use numbers
var arr2 = ["a","b","c"] // We can imagine this as another simple view

var nestedArr = [arr1,arr2] //in our analogy, we can now group views
//together and the structure that would hold that would be what we call the ViewGroup

Die ViewGroup ermöglicht es uns außerdem, die Anordnung der Kindelemente innerhalb der Ansicht festzulegen, beispielsweise vertikal oder horizontal. Wir können unterschiedliche Interaktionsregeln innerhalb der Ansicht definieren. So sollten beispielsweise aufeinanderfolgende TextViews einen Abstand von 12 dp haben, während ein ImageView gefolgt von einem TextView einen Abstand von 5 dp aufweisen sollte.

Dies wäre der Fall, wenn wir entwickeln würdenping Wir erstellen unsere eigene ViewGroup von Grund auf. Um diese Konfigurationen zu vereinfachen, Android stellt eine Klasse namens LayoutParams bereit, mit der wir diese Konfigurationen eingeben können.

Das Android Dokumentation Es werden einige Standardparameter bereitgestellt, die wir beim Konfigurieren unserer eigenen ViewGroup verwenden. Häufig verwendete Parameter betreffen Breite, Höhe und Rand. Standardmäßig haben diese Konfigurationen die Struktur `android:layout_height` für die Höhe und `android:layout_width` für die Breite. Beim Erstellen Ihrer ViewGroup können Sie darüber hinaus LayoutParams definieren, die das gewünschte Verhalten Ihrer ViewGroup festlegen.

Android Es enthält standardmäßige Ansichten und Ansichtsgruppen, mit denen wir viele gängige Aufgaben erledigen können. Ein Beispiel dafür ist die bereits erwähnte TextView. Diese einfache Ansicht bietet konfigurierbare Eigenschaften wie Höhe, Breite und Textgröße. Außerdem gibt es, wie bereits erwähnt, eine ImageView zur Bildanzeige und EditText sowie viele weitere Elemente. Android verfügt außerdem über benutzerdefinierte ViewGroups, zu denen wir unsere Ansichten hinzufügen und das erwartete Verhalten erzielen können.

LinearLayout

LinearLayout ermöglicht das Hinzufügen von View-Elementen. Es verfügt über ein Ausrichtungsattribut, das die Anordnung auf dem Bildschirm festlegt. Zusätzlich gibt es `LinearLayout.LayoutParams`, die die Regeln für die darin enthaltenen Views definieren. Beispielsweise zentriert das Attribut `android:center_horizontal` die Views horizontal, während `android:center_vertical` den Inhalt der View vertikal zentriert.

Hier sind einige Bilder, die das Zentrieren veranschaulichen. Wir gehen von einem einfachen TextView innerhalb eines 200 x 200 Pixel großen Bereichs aus; die Zentrierungsattribute würden folgendes Verhalten bewirken.

android:center_horizontal

Horizontal zentrierter Inhalt

Horizontal zentrierter Inhalt

android:center_vertical

Vertikal zentrierter Inhalt

Vertikal zentrierter Inhalt

android:center

Zentrierter Inhalt

Zentrierter Inhalt

Kernkomponenten von RecyclerView

Kernkomponenten von RecyclerView

Kernkomponenten von RecyclerView

Im Folgenden sind die wichtigen Komponenten von RecyclerView aufgeführt:

RecyclerView.Adapter

Grundlagen Nr. 1 – Adaptermuster

Ein Adapter ist ein Gerät, das die Eigenschaften eines Systems oder Geräts an die eines ansonsten inkompatiblen Geräts oder Systems anpasst. Manche Adapter verändern Signal- oder Stromversorgungseigenschaften, andere hingegen adaptieren lediglich die physische Form eines Steckers an einen anderen.

Ein einfaches Beispiel aus dem Alltag, das die Verwendung eines Adapters verdeutlicht: Man möchte Geräte miteinander verbinden, deren Anschlüsse aber nicht kompatibel sind. Das kann beispielsweise der Fall sein, wenn man in ein anderes Land reist, in dem andere Steckdosen verwendet werden. Mit dem mitgebrachten Handy- oder Laptop-Ladegerät kann man es dort nicht anschließen. Man gibt aber nicht auf, sondern verwendet einfach einen Adapter, der zwischen Steckdose und Ladegerät geschaltet wird und das Laden ermöglicht.

Dies ist der Fall in der Programmierung, wenn wir zwei Datenstrukturen miteinander verbinden wollen, um eine Aufgabe zu erfüllen, deren Standardports aber keine Möglichkeit zur Kommunikation untereinander bieten.

Wir verwenden das einfache Beispiel eines Geräts und eines Ladegeräts. Wir betrachten zwei Ladegeräte, ein amerikanisches und ein britisches.

class AmericanCharger() {
    var chargingPower = 10
}
class BritishCharger(){
    var chargingPower = 5
}

Wir werden dann zwei Geräte herstellen.

class AmericanDevice()
class BritishDevice()

Als Beispiel können wir dann einige Instanzen der Geräte zum Mitspielen erstellen.

var myAmericanPhone = new AmericanDevice()
var myBritishPhone = new BritishDevice()

Anschließend führen wir das Konzept des Ladens für beide Geräte ein, indem wir eine Methode namens `charge()` in den Geräten hinzufügen. Die Methode verwendet das jeweilige Ladegerät und führt den Ladevorgang entsprechend durch.

sealed trait Device
class AmericanDevice : Device{
    fun charge(charger:AmericanCharger){
        //Do some American charging
    }
}
class BritishDevice: Device{
    fun charge(charger:BritishCharger){
        //Do some British charging
    }
}

In diesem Fall würden wir, basierend auf unserer Analogie, aus dem einen oder anderen Grund ein britisches Ladegerät benötigen, wenn wir ein amerikanisches Gerät verwenden, oder umgekehrt.

In der Programmierwelt ist dies normalerweise der Fall, wenn Bibliotheken gemischt werden, die die gleiche Funktionalität bieten (in unserem Kontext ist unsere gemeinsame Funktionalität kostenpflichtig). Wir müssten einen Weg finden, dies zu ermöglichen.

Folgt man der Analogie, müssten wir in ein Elektronikgeschäft gehen und einen Adapter kaufen, mit dem wir amerikanische Geräte mit britischen Ladegeräten aufladen können. Aus Programmierersicht wären wir der Hersteller des Adapters.

Wir erstellen einen Adapter, der genau dem Muster entspricht, das wir für die Erstellung des anderen Adapters benötigen. Wir implementieren ihn als Klasse, wie folgt. Es muss nicht unbedingt eine Klasse sein; es könnte auch eine Funktion sein, die die allgemeine Funktionsweise des Adaptermusters verdeutlicht. Wir verwenden eine Klasse, da dies dem häufigsten Anwendungsfall entspricht. Android.

class AmericanToBritishChargerAdapter(theAmericanCharger:AmericanCharger){
    fun returnNewCharger(): BritishCharger{
            //convert the American charger to a BritishCharger
            //we would change the American charging functionality
            //to British charging functionality to make sure the
            //adapter doesn't destroy the device. The adapter could
            //, for example, control the power output by dividing by 2
            //our adapter could encompass this functionality in here

           var chargingPower:Int = theAmericanCharger.chargingPower / 2
           var newBritishCharger = new BritishCharger()
           newBritishCharger.chargingPower = theAmericanCharger.chargingPower/2

        return newBritishCharger
    }
}

In der Programmierwelt ist der Unterschied bei den Anschlüssen vergleichbar mit dem Unterschied bei den Lademethoden. Ladegeräte mit unterschiedlichen Lademethoden wären unbrauchbar.

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()

Der Versuch, die Methode `charge()` von `myBritishDevice` mit `americanChargerIFound` aufzurufen, schlägt fehl, da `AmericanDevice` nur `AmericanCharger` akzeptiert. Daher ist dies nicht möglich.

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()
myBritishDevice.charge(americanChargerIFound)

In diesem Szenario erweist sich der von uns erstellte Adapter „AmericanToBritishChargerAdapter“ als nützlich. Mit der Methode `returnNewCharger()` können wir ein neues „BritishCharger“-Objekt erstellen, das wir zum Laden verwenden können. Dazu erstellen wir lediglich eine Instanz unseres Adapters und übergeben ihr das vorhandene „AmericanCharger“-Objekt. Daraufhin wird ein „BritishCharger“-Objekt erstellt, das wir verwenden können.

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()
//We create the adapter and feed it the americanCharger
var myAdapter =  AmericanToBritishChargerAdapter(americanChargerIFound)
//calling returnNewCharger from myAdapter would return a BritishCharger
var britishChargerFromAdapter = myAdapter.returnNewCharger()
//and once we have the britishCharger we can now use it
myBritishDevice.charge(britishChargerFromAdapter)

RecyclerView.LayoutManager

Bei der Arbeit mit einer ViewGroup befinden sich darin platzierte Views. Der LayoutManager hat die Aufgabe, die Anordnung der Views innerhalb der ViewGroup zu beschreiben.

Zum Vergleich: Bei der Arbeit mit einer LinearLayout-ViewGroup möchten wir die Elemente entweder vertikal oder horizontal anordnen können. Dies lässt sich einfach realisieren, indem wir ein Ausrichtungsattribut hinzufügen, das angibt, wie das LinearLayout auf dem Bildschirm positioniert wird. Wir können dies mithilfe von … erreichen. android:orientation=VERTICAL|HORIZONTAL Attribut.

Wir haben außerdem eine weitere ViewGroup namens GridLayout. Sie dient dazu, Views in einer rechteckigen Rasterstruktur anzuordnen. Dies kann beispielsweise sinnvoll sein, um die dem App-Nutzer präsentierten Daten übersichtlicher zu gestalten. GridLayout bietet Konfigurationsmöglichkeiten, um dieses Ziel durch die Definition der Rasterdimensionen zu erreichen; beispielsweise ein 4×4- oder ein 3×2-Raster.

RecyclerView.ViewHolder

Der ViewHolder ist ein AbstracDie Klasse, die wir ebenfalls von RecyclerView erweitern, stellt uns ViewHolder zur Verfügung. Dieser bietet uns allgemeine Methoden, mit denen wir auf eine View zugreifen können, die wir in RecyclerView platziert haben, selbst nachdem die Recyclingmechanismen von RecyclerView verschiedene Referenzen geändert haben, von denen wir nichts wissen.

Große Listen

RecyclerViews werden verwendet, wenn wir dem Benutzer eine sehr große Anzahl von Ansichten präsentieren möchten, ohne dabei den Speicherplatz zu erschöpfen. RAM auf unserem Gerät für jede einzelne Instanz der erstellten Ansicht.

Nehmen wir als Beispiel eine Kontaktliste. Wir hätten dann eine allgemeine Vorstellung davon, wie ein Kontakt in der Liste aussehen würde. Anschließend würden wir ein Layout-Template erstellen, das eigentlich eine Ansicht (View) ist, mit Feldern, in die verschiedene Daten aus unserer Kontaktliste eingefügt werden. Der folgende Pseudocode verdeutlicht den gesamten Zweck:

//OneContactView
<OneContact>
<TextView>{{PlaceHolderForName}}</TextView>
<TextView>{{PlaceHolderForAddress}}</TextView>
<ImageView>{{PlaceHolderForProfilePicture}}</ImageView>
<TextView>{{PlaceHolderForPhoneNumber}}</TextView>
</OneContact>

Wir hätten dann eine Kontaktliste dieser Art:

<ContactList>
</ContactList>

Würden wir die Inhalte fest im Code verankern, hätten wir keine Möglichkeit, programmatisch neue Inhalte zur Liste hinzuzufügen, ohne die Anwendung neu zu schreiben. Glücklicherweise wird das Hinzufügen einer Ansicht zu einer Ansichtsgruppe von einer solchen Funktion unterstützt. addView(view:View) Methode. Dennoch ist dies nicht die Art und Weise, wie dem RecyclerView untergeordnete Ansichten hinzugefügt werden.

In unserem Anwendungsfall haben wir eine lange Kontaktliste. Für jeden Kontakt in der Liste müssen wir eine `OneContactView` erstellen und die Daten innerhalb dieser Ansicht entsprechend den Feldern unserer `Contact`-Klasse befüllen. Anschließend müssen wir die Ansicht dem `RecyclerView` hinzufügen, um die Liste anzuzeigen.

data  class Contact(var name:String, var address:String, var pic:String, var phoneNumber:Int)

var contact1 = Contact("Guru","Guru97", "SomePic1.jpg", 991)
var contact2 = Contact("Guru","Guru98", "SomePic2.jpg", 992)
var contact3 = Contact("Guru","Guru99", "SomePic3.jpg", 993)

var myContacts:ArrayList<Contact> = arrayListOf<Contact>(contact1,contact2,contact3)

Wir haben ein Array von Kontakten. Die OneContactView enthält Slots, um Inhalte aus der Contact-Klasse zu übernehmen und anzuzeigen. In der RecyclerView müssen wir Views hinzufügen, damit sie die Wiederverwertungsfunktion nutzen kann.

Der RecyclerView erlaubt es uns nicht, eine Ansicht hinzuzufügen, sondern nur einen ViewHolder. In diesem Fall möchten wir also zwei Komponenten verbinden, die nicht zusammenpassen. Hier kommt unser Adapter ins Spiel. Der RecyclerView stellt uns einen Adapter zur Verfügung, ähnlich wie unser AmericanToBritishChargerAdapter() Das hat uns zuvor ermöglicht, unseren amerikanischen Ladeadapter, der mit unserem britischen Gerät unbrauchbar war, in etwas Brauchbares umzuwandeln, das einem Netzteil im realen Leben ähnelt.

In diesem Szenario würde der Adapter unser Array von Kontakten und unsere Ansicht entgegennehmen und daraus ViewHolder generieren, die der RecyclerView akzeptieren kann.

Der RecyclerView bietet eine Schnittstelle, die wir erweitern können, um unseren Adapter über die Klasse `RecyclerView.Adapter` zu erstellen. Innerhalb dieses Adapters befindet sich eine Möglichkeit, die ViewHolder-Klasse zu erstellen, mit der der RecyclerView arbeiten soll. Wir haben also dieselbe Situation wie zuvor, nur mit einer zusätzlichen Komponente: dem Adapter.

Wir haben ein Array von Kontakten, eine Ansicht zur Anzeige eines einzelnen Kontakts (OneContactView) und einen RecyclerView, eine Liste von Ansichten, die Recycling-Dienste bereitstellt, aber nur ViewHolder akzeptiert. In diesem Szenario haben wir nun eine RecyclerView.Adapter-Klasse, die eine Methode zum Erstellen von ViewHoldern enthält.

fun createViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder

Der RecyclerView.ViewHolder ist ein absolutertracDie Klasse nimmt unsere View als Argument entgegen und konvertiert sie in einen ViewHolder. Sie verwendet das Wrapper-Muster, das zur Erweiterung der Funktionalität von Klassen dient.

Grundarbeit Nr. 2 – Wrapper-Muster

Anhand eines einfachen Beispiels werden wir demonstrieren, wie wir Tiere zum Sprechen bringen können.

sealed trait Animal{
    fun sound():String
}

data class Cat(name:String):Animal{
    fun sound(){
        "Meow"
        }
}
data class Dog(name:String):Animal{
    fun sound(){
        "Woof"
        }
}

var cat1 = Cat("Tubby")
var dog1 = Dog("Scooby")
cat1.sound() //meow
dog1.sound() //woof

Im obigen Beispiel haben wir zwei Tiere. Falls wir ihnen aus irgendeinem Grund eine Sprachausgabe hinzufügen wollten, der Bibliotheksautor aber nicht kooperativ war, könnten wir trotzdem eine Lösung finden. Wir bräuchten dazu einen Wrapper für unsere Tierklasse. Diesen würden wir erreichen, indem wir das Tier als Konstruktor für unsere Klasse verwenden.

class SpeechPoweredAnimalByWrapper(var myAnimal:Animal){

    fun sound(){
        myAnimal.sound()
    }

    fun speak(){
        println("Hello, my name is ${myAnimal.name}")
    }
}

Nun können wir eine Tierinstanz an den SpeechPoweredAnimalByWrapper übergeben. Der Aufruf der Methode `sound()` ruft die entsprechende Methode `sound()` des übergebenen Tieres auf. Zusätzlich gibt es eine Methode `speak()`, die als neue Funktionalität für die übergebenen Tiere gilt. Die Verwendung ist wie folgt:

var cat1 =  Cat("Garfield")
cat1.sound()//"meow"
cat1.speak()// doesn't work as it isn't implemented
var talkingCat = new SpeechPoweredAnimalByWrapper(cat1)
talkingCat.sound() //"meow" the sound method calls the one defined for cat1
talkingCat.speak() //"Hello, my name is Garfield"

Mithilfe dieses Musters können wir Klassen nehmen und ihnen Funktionalität hinzufügen. Wir müssen lediglich eine Klasseninstanz und die neuen, durch unseren Wrapper definierten Methoden übergeben.ping Klasse.

Im obigen Fall haben wir eine konkrete Klasse verwendet. Es ist auch möglich, dasselbe in einer abstrakten Sprache zu implementieren.tract-Klasse. Wir müssten die Klasse SpeechPoweredAnimalByWrapper in abs ändern.tract, und damit sind wir fertig. Wir werden den Klassennamen kürzen, um ihn besser lesbar zu machen.

abstract class SpeechPowered(var myAnimal:Animal){

    fun sound(){
        myAnimal.sound()
    }

    fun speak(){
        println("Hello, my name is ${myAnimal.name}")
    }
}

Es ist dasselbe wie zuvor, aber es hätte eine andere Bedeutung. In einer normalen Klasse können wir eine Instanz einer Klasse auf dieselbe Weise erzeugen, wie wir cat1 und dog1 erzeugt haben. Abstract-Klassen sind jedoch nicht zur Instanziierung gedacht, sondern dienen der Erweiterung anderer Klassen. Wie würden wir also den neuen SpeechPowered(var myAnimal:Animal)-Abs verwenden?tract-Klasse? Wir können sie nutzen, indem wir neue Klassen erstellen, die sie erweitern und dadurch ihre Funktionalität erhalten.

In unserem Beispiel erstellen wir eine Klasse SpeechPoweredAnimal, die die Klasse erweitert.

class SpeechPoweredAnimal(var myAnimal:Animal):SpeechPowered(myAnimal)
var cat1 =  Cat("Tubby")
var speakingKitty = SpeechPoweredAnimal(cat1)
speakingKitty.speak() //"Hello, my name is Tubby"

Dies ist dasselbe Muster, das im ViewHolder verwendet wird. Die Klasse RecyclerView.ViewHolder ist ein absoluter ViewHolder.tracEine Klasse, die der Ansicht zusätzliche Funktionalität hinzufügt, ähnlich wie wir den Tieren die Sprechmethode hinzugefügt haben. Diese zusätzliche Funktionalität ermöglicht die Interaktion mit dem RecyclerView.

So erstellen wir einen OneContactViewHolder aus OneContactView:

//The View argument we pass is converted to a ViewHolder which uses the View to give it more abilities and in turn work with the RecyclerView
class OneContactViewHolder(ourContactView: View) : RecyclerView.ViewHolder(ourContactView)

RecyclerView verfügt über einen Adapter, der es uns ermöglicht, unser Kontakte-Array mit der ContactsView über RecyclerView zu verbinden.

Ansicht hinzufügen

Die ViewGroup wird nicht automatisch neu gezeichnet, sondern folgt einem bestimmten Zeitplan. Auf Ihrem Gerät kann die Neuzeichnung beispielsweise alle 10 ms oder 100 ms erfolgen. Oder, wenn wir einen unrealistischen Wert wählen, beispielsweise 1 Minute, werden die Änderungen beim Hinzufügen einer Ansicht zu einer ViewGroup 1 Minute später sichtbar, wenn die ViewGroup aktualisiert wird.

RecyclerView.Recycler

Grundlagen #3 – Geocaching

Eines der besten Beispiele dafür, wo wir regelmäßig Seiten aktualisieren, ist der Browser. Stellen wir uns beispielsweise vor, die Website, die wir besuchen, ist statisch und sendet keine dynamischen Inhalte; wir müssten die Seite ständig aktualisieren, um die Änderungen zu sehen.

Nehmen wir als Beispiel Twitter. Dort würden statische Tweets aufgelistet, und neue Tweets könnten nur durch Klicken auf die Aktualisierungsschaltfläche angezeigt werden.

Das Neuladen des gesamten Bildschirms ist offensichtlich kostspielig. Stellen Sie sich vor, wir hätten nur begrenztes Datenvolumen bei unserem Mobilfunkanbieter und unsere Tweet-Liste enthielte viele Bilder und Videos; es wäre teuer, den gesamten Seiteninhalt bei jedem Aktualisieren neu herunterzuladen.

Wir benötigen eine Möglichkeit, die bereits geladenen Tweets zu speichern und sicherzustellen, dass unsere nächste Anfrage angibt, welche Tweets bereits vorhanden sind. Dadurch werden nicht alle Tweets erneut heruntergeladen, sondern nur die neuen abgerufen. Zusätzlich wird geprüft, ob ein lokal gespeicherter Tweet nicht mehr vorhanden ist, um ihn gegebenenfalls lokal zu löschen. Dieses Verfahren nennt man Caching.

Die Informationen, die wir über die Inhalte unserer Website senden, werden Metadaten genannt. Wir sagen also nicht einfach nur „Wir möchten Ihre Website laden“, sondern „Wir möchten Ihre Website laden und hier sind einige Inhalte, die wir beim letzten Laden gespeichert haben; bitte verwenden Sie diese, um uns nur die fehlenden Daten zu senden, damit wir nicht unnötig Bandbreite verbrauchen.“

Layout-Aufrufe – Die Tweet-Liste muss verrückt sein

Ein Beispiel für einen Layoutaufruf ist `scrollToPosition`. Dies ist ein häufiges Beispiel, etwa in Chat-Apps. Wenn jemand in einem Chatverlauf auf eine vorherige Chatblase antwortet, fügen manche Chat-Apps die Antwort und einen Link zur Chatblase hinzu. Ein Klick darauf führt zurück zur ursprünglichen Nachricht.

Falls wir diese Methode aufrufen, bevor wir einen LayoutManager zu unserem RecyclerView hinzugefügt haben und bevor wir einen RecyclerView.Adapter haben, wird scrollToPosition(n:Int) einfach ignoriert.

Kommunikation zwischen RecyclerView-Komponenten

Grundlagen #4 – Rückrufe

Der RecyclerView ist ein komplexes System mit vielen Komponenten. Er interagiert mit dem LayoutManager, der die Anordnung der Views – linear oder in einem Raster – festlegt. Außerdem benötigt er einen Adapter, der die Elemente (Kontaktliste) in Views (OneContactView) und anschließend in ViewHolder (OneContactViewHolder) umwandelt, mit denen der RecyclerView mithilfe seiner Methoden arbeiten kann.

Das Rohmaterial für den RecyclerView sind unsere Views, z. B. OneContactView, und eine Datenquelle.

contactList:Array<Contact>

Wir haben ein einfaches Szenario als Ausgangspunkt gewählt, um zu verstehen, was der RecyclerView leisten soll. Ein Basisfall mit einem statischen Array von 1000 Kontakten, das wir dem Benutzer anzeigen möchten, ist leicht verständlich. Der RecyclerView entfaltet sein volles Potenzial jedoch erst, wenn die Liste nicht mehr statisch ist. Bei einer dynamischen Liste müssen wir berücksichtigen, was mit der Ansicht auf dem Bildschirm passiert, wenn wir ein Element hinzufügen oder entfernen.

RecyclerView.LayoutManager

Abgesehen von der Entscheidung, wie unsere Ansichten angeordnet werden, entweder linear oder in einem Raster, erledigt der LayoutManager im Hintergrund eine Menge Arbeit.ping Der Recyclingbetrieb weiß, wann Recycling ansteht.

Es ist verantwortlich für die Keeping tracDer LayoutManager erfasst die Anzahl der aktuell auf dem Bildschirm sichtbaren Ansichten und übermittelt diese Information an den Recyclingmechanismus. Beim Scrollen nach unten informiert der LayoutManager das Recyclingsystem über die Ansichten, die am oberen Rand den Fokus verlieren, damit diese wiederverwendet werden können, anstatt dort zu verbleiben und Speicher zu belegen oder zerstört zu werden, nur um neue zu erstellen.

Das bedeutet, dass der LayoutManager Folgendes beibehalten muss: track gibt die Position des Nutzers beim Scrollen durch unsere Liste an. Dies geschieht mithilfe einer Liste von Positionen, die indexbasiert sind, d. h. das erste Element beginnt bei 0 und wird entsprechend der Anzahl der Elemente in unserer Liste erhöht.

Wenn wir zu Beginn 10 Elemente unserer Liste mit beispielsweise 100 Elementen sehen können, weiß der LayoutManager, dass er die Ansichten View-0 bis View-9 im Fokus hat. Beim Scrollen kann der LayoutManager die Ansichten berechnen, die den Fokus verlieren.

Der LayoutManager kann diese Ansichten dem Recyclingmechanismus übergeben, sodass sie wiederverwendet werden können (neue Daten können an sie gebunden werden; z. B. können die Kontaktdaten einer Ansicht entfernt und neue Kontaktdaten aus dem nächsten Segment die Platzhalter ersetzen).

Das wäre ideal, wenn die Liste statisch wäre. RecyclerViews werden aber häufig mit dynamischen Listen verwendet, deren Daten von einem Online-Endpunkt oder sogar von einem Sensor stammen können. Dabei werden nicht nur Daten hinzugefügt, sondern auch entfernt oder aktualisiert.

Der dynamische Zustand unserer Daten kann die Funktionsweise des LayoutManagers erheblich erschweren. Aus diesem Grund verwaltet der LayoutManager eine eigene Liste der Elemente und Positionen, getrennt von der Liste, die die Recycling-Komponente verwendet. Dies gewährleistet die korrekte Ausführung des Layouts.

Gleichzeitig möchte der LayoutManager des RecyclerView die vorhandenen Daten korrekt darstellen. Um korrekt zu funktionieren, synchronisiert er sich in regelmäßigen Abständen (60 ms) mit dem RecyclerView.Adapter und übermittelt Informationen über die Listenelemente, z. B. hinzugefügte, aktualisierte, entfernte oder verschobene Elemente. Nach Erhalt dieser Informationen passt der LayoutManager die Bildschirminhalte entsprechend den Änderungen an.

Viele der Kernoperationen, die sich mit RecyclerView befassen, drehen sich um die Kommunikation zwischen dem RecyclerView.LayoutManager und dem RecyclerView.Adapter, der unsere Listen mit manchmal statischen oder manchmal dynamischen Daten speichert.

Darüber hinaus stellt uns RecyclerView Methoden zur Verfügung, mit denen wir auf Ereignisse reagieren können, wie beispielsweise onBindViewHolder, wenn unser RecyclerView.Adapter Inhalte aus unserer Liste (z. B. einen Kontakt) an einen ViewHolder bindet, damit dieser zur Anzeige der Informationen auf dem Bildschirm verwendet wird.

Eine weitere Methode ist onCreateViewHolder, die uns mitteilt, wann der RecyclerView.Adapter eine reguläre View wie OneContactView nimmt und sie in ein ViewHolder-Element umwandelt, mit dem der RecyclerView arbeiten kann.

Abgesehen von den Kernmechanismen, die das Recycling ermöglichen, bietet der RecyclerView Möglichkeiten zur Verhaltensanpassung, ohne das Recycling zu beeinträchtigen. Die Wiederverwendung von Views erschwert jedoch gängige Aktionen, die wir von statischen Views gewohnt sind, wie beispielsweise die Reaktion auf onClick-Ereignisse.

Wie wir wissen, RecyclerView.LayoutManager die dem Benutzer die Ansichten präsentiert, könnte für einen Moment eine andere Liste von Elementen haben als die RecyclerView.Adapter Die Liste wird in einer Datenbank gespeichert oder von einer Quelle gestreamt. Das direkte Platzieren von OnClick-Ereignissen auf Ansichten kann zu unerwartetem Verhalten führen, z. B. zum Löschen des falschen Kontakts.

Gradle

Um RecyclerView zu verwenden, muss es als Abhängigkeit in der build.gradle-Datei hinzugefügt werden. Im folgenden Beispiel wurde die Implementierung „androidx.recyclerview:recyclerview:1.1.0“ verwendet, die laut diesem Artikel die aktuellste Version ist.

Nach dem Hinzufügen der Abhängigkeit zu unserem Gradle Datei werden wir aufgefordert, Android Studio um die Änderungen zu synchronisieren. So funktioniert unser Gradle Die Datei kümmert sich darum, nachdem man in einem leeren Projekt mit den Standardeinstellungen einen RecyclerView hinzugefügt hat.

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.guru99.learnrecycler"
        minSdkVersion 17
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
             'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation "androidx.recyclerview:recyclerview:1.1.0"
}

Wir haben momentan nur eine Layoutdatei. Wir beginnen mit einem einfachen Beispiel, in dem wir einen RecyclerView verwenden, um eine Liste von Fruchtnamen auf dem Bildschirm anzuzeigen.

Liste von Gegenständen

Wir werden zu unserer MainActivity-Datei navigieren und direkt vor der onCreate()-Methode, die während der Einrichtung generiert wurde, ein Array mit Fruchtnamen erstellen.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Unser nächstes Ziel ist es, diese Liste mithilfe eines RecyclerView auf dem Bildschirm darzustellen. Dazu navigieren wir zum Layout-Verzeichnis, das unsere Layouts enthält, und erstellen eine View, die für die Anzeige einer einzelnen Frucht zuständig ist.

Layout, das für jedes Element in unserer Liste verwendet werden soll

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fruitName"
    />
</TextView>

Im obigen TextView haben wir ein ID-Feld hinzugefügt, das zur Identifizierung einer View dient. Es wird nicht standardmäßig generiert. Wir haben unserem TextView die ID „fruitName“ gegeben, um die Daten zuzuordnen, die daran gebunden werden.

Hinzufügen der RecyclerView zum Hauptlayout

In derselben Aktivität gibt es eine standardmäßig generierte Layoutdatei namens main_layout.xml. Wenn wir ein leeres Projekt ausgewählt haben, wurde automatisch eine solche Datei generiert. XML Wir werden den gesamten Inhalt eines ConstraintLayouts löschen und das Layout so anpassen, dass es nur noch den RecyclerView enthält (siehe unten).

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/fruitRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

Wir haben außerdem ein id-Attribut für den RecyclerView hinzugefügt, mit dem wir in unserem Code darauf verweisen werden.

android:id="@+id/fruitRecyclerView"

Anschließend kehren wir zu unserer MainActivity-Datei zurück. Mithilfe der erstellten IDs können wir auf die soeben erstellten Views zugreifen. Wir beginnen mit dem Zugriff auf den RecyclerView mithilfe der Methode `findViewById()`, die von der Bibliothek bereitgestellt wird. AndroidWir werden dies in unserer onCreate()-Methode tun. Unsere onCreate()-Methode sieht wie folgt aus.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
}

Erstellen Sie einen ViewHolder

Als Nächstes erstellen wir einen RecyclerView.ViewHolder, der unsere View in einen ViewHolder umwandelt, den der RecyclerView zur Anzeige unserer Elemente verwendet. Dies geschieht direkt nach der onCreate()-Methode.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

}

Erstellen Sie einen RecyclerViewAdapter

Als Nächstes erstellen wir eine Klasse `FruitArrayAdapter`, die von der Klasse `RecyclerView.Adapter` erbt. Der von uns erstellte `FruitArrayAdapter` ist für Folgendes zuständig: Er liest die Fruchtnamen aus dem Frucht-Array, erstellt einen ViewHolder mithilfe unserer Ansicht `one_fruit_view.xml`, bindet die Früchte an den ViewHolder und bindet dessen Inhalt dynamisch an die erstellte Ansicht.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

    class FruitArrayAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>()
}

Android Studio wird rote Wellenlinien auf unserem FruitArrayAdapter hinzufügen, was uns darauf hinweist, dass wir Methoden implementieren müssen, die der RecyclerView verwenden kann, um unser Array mit einem ViewHolder zu verbinden.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

     }

     override fun getItemCount(): Int {

     }

     override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

     }
 }

Wir beginnen mit dem einfachsten Teil des generierten Codes, der Methode `getItemCount()`. Wir wissen, wie wir die Anzahl der Elemente in unserem Array ermitteln, indem wir die Eigenschaft `size` des Arrays aufrufen.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

        }

        override fun getItemCount(): Int {
         return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

        }
    }

Anschließend implementieren wir die Methode `onCreateViewHolder`. Hier bittet uns der RecyclerView um Unterstützung beim Erstellen eines `FruitViewHolder`. Zur Erinnerung: So sah unsere `FruitViewHolder`-Klasse aus:

class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

Dazu benötigen wir unsere fruitView, die wir als XML-Datei one_fruit_view.xml erstellt haben. Wir können eine Referenz auf diese XML-Datei erstellen und sie wie folgt in eine View konvertieren.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder

        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

        }
    }

Der verbleibende Teil ist die Überschreibung von onBindViewHolder.

fun onBindViewHolder(holder: FruitViewHolder, position: Int)

Der RecyclerView.Adapter fragt nach einer Positionsangabe (Integer), mit der wir ein Element aus unserer Liste abrufen. Er stellt uns außerdem einen ViewHolder bereit, mit dem wir das Element aus dem `fruitArray` an die darin enthaltene View binden können. Die View im ViewHolder ist über das Feld `ViewHolder.itemView` zugänglich. Sobald wir die View haben, können wir den Inhalt mithilfe der zuvor erstellten ID `fruitName` festlegen.

override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

          var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

          var aFruitName = fruitArray.get(position)

          ourFruitTextView.setText(aFruitName)
      }

Damit ist unser FruitArrayAdapter fertiggestellt und sieht wie folgt aus.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder
        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

            var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

            var aFruitName = fruitArray.get(position)

            ourFruitTextView.setText(aFruitName)
        }
    }

Schließlich sind wir bereit, die restlichen Teile unseres RecyclerView zu verbinden. Dazu gehört die Erstellung eines LayoutManagers, der dem RecyclerView mitteilt, wie der Inhalt der Liste angezeigt werden soll, entweder linear mit Hilfe des LinearLayoutManager oder in einem Raster mit Hilfe des GridLayoutManager oder des StaggeredGridLayoutManager.

Erstellen Sie einen Layout-Manager

Wir kehren nun zu unserer onCreate-Funktion zurück und fügen den LayoutManager hinzu.

override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

       var fruitLinearLayout = LinearLayoutManager(this)

       myFruitRecyclerView.layoutManager =fruitLinearLayout

   }

Hängen Sie unseren Adapter an Elemente an und stellen Sie ihn auf RecyclerView ein

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

        var fruitLinearLayout = LinearLayoutManager(this)

        myFruitRecyclerView.layoutManager =fruitLinearLayout

        var fruitListAdapter = FruitListAdapter(fruitNames)

        myFruitRecyclerView.adapter =fruitListAdapter
    }

Wir haben außerdem eine Instanz von `fruitListAdapter` erstellt und ihr das Array mit den Fruchtnamen übergeben. Damit sind wir im Prinzip fertig. Die vollständige Datei `MainActivity.kt` sieht wie folgt aus.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

        var fruitLinearLayout = LinearLayoutManager(this)

        myFruitRecyclerView.layoutManager =fruitLinearLayout

        var fruitListAdapter = FruitListAdapter(fruitNames)

        myFruitRecyclerView.adapter =fruitListAdapter
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

    class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder
        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

            var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

            var aFruitName = fruitArray.get(position)

            ourFruitTextView.setText(aFruitName)
        }
    }
}

Laden Sie das Projekt herunter

Häufig gestellte Fragen

RecyclerView ist der flexiblere und effizientere Nachfolger von ListView. Es erzwingt das ViewHolder-Muster, unterstützt lineare, Raster- und gestaffelte Layouts durch Layout-Manager und bietet integrierte Elementanimationen, während ListView standardmäßig keine dieser Funktionen bietet.

GridView zeigt Elemente nur in einem festen Raster an. RecyclerView kann mithilfe des GridLayoutManagers zwar ein Raster erzeugen, unterstützt aber zusätzlich lineare und gestaffelte Layouts, die Wiederverwendung von Ansichten und Animationen und ist damit deutlich vielseitiger als GridView.

Dieses RecyclerView-Beispiel ist in Kotlin geschrieben, der offiziell empfohlenen Sprache von Google für Android Entwicklung. Die gleichen RecyclerView-, Adapter- und Layout-Manager-APIs funktionieren auch in Java.

Fügen Sie einen Klick-Listener innerhalb des ViewHolders oder in onBindViewHolder ein und stellen Sie ihn anschließend über einen Interface-Callback der Activity oder dem Fragment zur Verfügung. Durch die Verwendung der ViewHolder-Position wird verhindert, dass Klicks dem falschen wiederverwendeten Element zugeordnet werden.

DiffUtil ist eine Hilfsklasse, die die Differenz zwischen zwei Listen berechnet und die minimalen Aktualisierungen an den Adapter sendet. Sie ermöglicht effiziente dynamische Listenänderungen und automatisiert Hinzufügungen, Entfernungen und Verschiebungen.

Jetpack Compose verwendet für neue Bildschirme LazyColumn und LazyRow anstelle von RecyclerView. RecyclerView ist jedoch in bestehenden View-basierten Projekten weiterhin weit verbreitet und kann über Interoperabilitäts-APIs in Compose eingebunden werden.

Ja. KI-Assistenten wie GitHub Copilot und GPT-basierte Tools können anhand kurzer Eingabeaufforderungen einen RecyclerView-Adapter, einen ViewHolder und eine onBindViewHolder-Methode generieren. Entwickler sollten den generierten Code dennoch auf Korrektheit und Performance überprüfen.

Maschinelles Lernen Android Apps nutzen RecyclerView, um dynamische Ausgaben wie Empfehlungen, Suchergebnisse oder Bildklassifizierungen darzustellen. Der Adapter bindet Modellergebnisse an Listenelemente, sodass große, sich häufig ändernde Datensätze flüssig scrollen können.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: