In dieser Lektion werden wir das Datenmodell für die Zeilen des ListViews definieren. Dazu werden wir die Java-Klasse Quote.java
anlegen. Mit Hilfe dieser Klasse werden wir die auszugebenden Inhalte der ListView-Zeilen speichern.
Jede Zeile des ListViews besteht aus drei View-Elementen, einem ImageView und zwei TextViews. Der ImageView gibt das Autorenbild aus, die beiden TextViews den Zitattext und den dazugehörenden Autorennamen.
Diesen Zeilenaufbau werden wir mit der Quote-Klasse nachbilden, so dass Instanzen dieser Klasse sämtliche Daten einer ListView-Zeile in sich aufnehmen können. Diese Instanzen (Quote-Objekte) speichern wir in einer ArrayList, die von uns als Datenquelle für den ListView genutzt werden wird.
In Bezug auf die beiden vorherigen Lektionen ist diese Lektion als dritter von vier Arbeitsschritten zu sehen, die für die Verbindung von Daten und Layout notwendig sind.
Zu Beginn dieser Lektion werden wir die Klasse Quote.java
in Android Studio erstellen und in ihr das Datenmodell unseres ListViews implementieren. Anschließend erzeugen wir einige Quote-Objekte und füllen mit ihnen eine ArrayList, die uns im weiteren Verlauf dieses Kurses als Datenquelle dienen wird.
Diese Datenquelle werden wir dann über einen normalen ArrayAdapter mit dem bereits integrierten ListView verbinden. Der Adapter wird die Quote-Objekte aus der Datenquelle extrahieren und deren Inhalte dem Zeilenlayout, also den Zeilen des ListViews, zuweisen.
Abschließend werden wir unsere Android App im Emulator auf einem Android Virtual Device ausführen und die korrekte Funktionsweise des ListViews überprüfen.
1. Erstellen der Datenmodell-Klasse Quote.java
Wir werden nun die Java Klasse Quote unserem Android Studio Projekt hinzufügen. Mit ihrer Hilfe werden wir die Zeilen unseres ListViews nachbilden. Jede ListView-Zeile besteht aus genau drei View-Elementen, einem ImageView-Element und zwei TextView-Elementen. Mit Hilfe des ImageViews wird ein kleines Autorenbild dargestellt. Die beiden TextView-Elemente sind für die Darstellung des Zitat-Texts und -Autors verantwortlich.
In der unteren Abbildung ist der Aufbau der ListView-Zeilen noch einmal dargestellt:
Diesen Zeilenaufbau werden wir mit der neuen Klasse Quote nachbilden, so dass eine Instanz dieser Klasse sämtliche Daten einer ListView-Zeile in sich aufnehmen kann. Die Daten, Bild-ID, Zitattext und Autorenname, werden dazu in den Membervariablen der Quote-Klasse gespeichert. Über get-Methoden kann später von außen auf die, in dem Quote-Objekten gespeicherten, Daten zugegriffen werden.
Um die Datenmodell-Klasse Quote anzulegen, muss eine neue Java Klassendatei in dem Package-Ordner unseres Projekts erstellt werden. Dafür gibt es zwei Vorgehensweisen: über die obere Menüleiste oder über den Package-Ordner in der Project-Ansicht. Wir werden den zweiten Weg wählen, da er intuitiver und weniger fehleranfällig ist.
Als Erstes muss dafür die Project-Ansicht exakt so wie in Lektion 4 Abschnitt 2 beschrieben aufgeklappt werden. In diesen Package-Ordner werden wir nun die neue Klassendatei mit Hilfe des Create New Class-Dialog von Android Studio anlegen lassen.
Die Klassendatei Quote.java
unseres Datenmodells legen wir nun folgendermaßen an:
- Mit der rechten Maustaste auf den Package-Ordner de.codeyourapp.zitate klicken.
- Anschließend den Eintrag New des Kontext-Menüs anklicken.
- Danach auf den Eintrag Java Class klicken.
Anschließend öffnet sich der Create New Class-Dialog, der uns bei der Erstellung der neuen Java Klasse unterstützt. Wir müssen nur einige Felder des Dialogs ausfüllen.
In dem Create New Class-Dialog nehmen wir nun die folgenden Einstellungen vor:
- Als Klassennamen tragen wir in das Feld Name Quote ein.
- Den Wert für Kind lassen wir auf Class stehen.
- Die Felder Superclass und Interface(s) lassen wir leer.
- Als Package sollte bereits automatisch unser Package-Ordner de.codeyourapp.zitate eingetragen sein.
- Alle anderen Einstellungen übernehmen wir unverändert.
- Den Dialog bestätigen wir mit einem Klick auf den OK Button.
Android Studio legt nun automatisch die neue Java Klasse an. Dabei wird auch der minimale Quellcode für das Klassengerüst erzeugt. Diesen benötigen wir aber nicht und werden ihn daher vollständig durch unseren eigenen Code ersetzen.
Dazu öffnen wir die Klassendatei Quote.java
im Editorfenster von Android Studio mit einem Doppelklick auf den entsprechenden Eintrag in der linken Project-Ansicht.
Anschließend ersetzen wir den gesamten Quelltext mit folgendem Code:
Quote.java
package de.codeyourapp.zitate; public class Quote { private final String quoteText; private final String quoteAuthor; private final String imageId; public Quote(String quoteText, String quoteAuthor, String imageId) { this.quoteText = quoteText; this.quoteAuthor = quoteAuthor; this.imageId = imageId; } public String getQuoteText() { return quoteText; } public String getQuoteAuthor() { return quoteAuthor; } public String getImageId() { return imageId; } @Override public String toString() { String output = quoteText + " - " + quoteAuthor + " - ID: " + imageId; return output; } }
Die Quote-Klasse ist sehr einfach aufgebaut. Sie besitzt die drei Membervariable quoteText, quoteAuthor und imageId. Alle drei Variable sind als final deklariert. Ihnen kann daher nur einmal ein Wert zugewiesen werden. Auf die Inhalte dieser Variablen kann über die drei get-Methoden zugegriffen werden.
Der Konstruktor in den Zeilen 9 bis 13 füllt die drei Instanzvariablen mit Werten. Da die zugewiesenen Werte unveränderlich in den Variablen gespeichert werden, sind set-Methoden überflüssig und daher auch nicht in der Quote-Klasse implementiert.
Mit der überschriebenen toString() Methode in den Zeilen 28 bis 32 lassen wir den Inhalt der drei Variablen in einem String zusammenfassen. Diese Methode wird später automatisch vom normalen ArrayAdapter aufgerufen, um Inhalte aus der Datenquelle zu extrahieren. Auf diese Weise können wir prüfen, ob unser Datenmodell die zugewiesenen Inhalte korrekt in den Instanzvariablen abspeichert.
In Android Studio sollte die Klassendatei Quote.java
nun wie folgt aussehen:
In der oberen Abbildung ist die Klasse Quote im Editor von Android Studio bereits geöffnet. Der weiter oben aufgeführte Quellcode wurde schon eingefügt. Die Klasse besitzt die drei Membervariablen quoteText, quoteAuthor und imageId, auf die mit Hilfe der get-Methoden zugegriffen werden kann.
Mit dem Konstruktor können wir die Quote-Objekte erzeugen lassen. Die drei Instanzvariablen quoteText, quoteAuthor und imageId werden beim Erzeugen der Objekte direkt mit den übergebenen Werten gefüllt.
Von jetzt an werden wir die Quote-Klasse nutzen, um die Datensätze des ListViews in Java-Objekten zu speichern. Jedes Objekt entspricht dann exakt einer Zeile des ListViews. Wir können dann mit den Objekten in unserem Code weiterarbeiten und ihren Inhalt mit Hilfe des ListViews ausgeben lassen.
Als Nächstes werden wir mehrere Quote-Objekte zu Testzwecken manuell erstellen und mit ihnen die Datenquelle unseres ListViews befüllen.
2. Füllen der Datenquelle mit Objekten des Datenmodells
Wir werden nun zu Testzwecken einige Zitate erstellen und mit ihnen die Datenquelle unseres ListViews befüllen. Dazu lassen wir in der MainActivity-Klasse mehrere Instanzen der Datenmodell-Klasse Quote erzeugen. Diese Quote-Objekte fügen wir anschließend einer ArrayList hinzu. Diese ArrayList wird uns dann als Datenquelle des ListViews dienen.
Um die notwendigen Änderungen am Quellcode durchzuführen, öffnen wir die Klassendatei MainActivity.java
im Editor von Android Studio. Dazu klicken wir doppelt auf ihren Dateinamen im Project Tool Window. Die Klassendatei befindet sich im Package-Ordner de.codeyourapp.zitate unseres Projekts.
Dem Quellcode der MainActivity.java
Datei fügen wir nun die grau markierten Zeilen hinzu:
MainActivity.java
package de.codeyourapp.zitate; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.widget.ArrayAdapter; import android.widget.ListView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends AppCompatActivity { public static final String LOG = MainActivity.class.getSimpleName(); private List<String> mSampleQuoteList; private List<Quote> mQuoteList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); createQuoteList(); bindAdapterToListView(); } private void createQuoteList() { String[] sampleQuotes = getResources().getStringArray(R.array.sample_quotes); mSampleQuoteList = new ArrayList<>(Arrays.asList(sampleQuotes)); Quote sampleQuote = new Quote(sampleQuotes[0], "Johann Wolfgang v. Goethe", "goethe"); mQuoteList.add(sampleQuote); mQuoteList.add(new Quote(sampleQuotes[1], "Friedrich Schiller", "schiller")); mQuoteList.add(new Quote(sampleQuotes[2], "Johann Wolfgang v. Goethe", "goethe")); mQuoteList.add(new Quote(sampleQuotes[3], "Friedrich Schiller", "schiller")); mQuoteList.add(new Quote(sampleQuotes[4], "Johann Wolfgang v. Goethe", "goethe")); mQuoteList.add(new Quote(sampleQuotes[5], "Friedrich Schiller", "schiller")); mQuoteList.add(new Quote(sampleQuotes[6], "Johann Wolfgang v. Goethe", "goethe")); mQuoteList.add(new Quote(sampleQuotes[7], "Friedrich Schiller", "schiller")); mQuoteList.add(new Quote(sampleQuotes[8], "Johann Wolfgang v. Goethe", "goethe")); mQuoteList.add(new Quote(sampleQuotes[9], "Unbekannt", "unknown")); } private void bindAdapterToListView() { ArrayAdapter<String> quoteArrayAdapter = new ArrayAdapter<>( this, // Die aktuelle Umgebung (diese Activity) R.layout.list_row, // Die ID des Zeilenlayouts (der XML-Layout Datei) R.id.quote_text, // Die ID eines TextView-Elements im Zeilenlayout mSampleQuoteList); // Beispieldaten in einer ArrayList ListView quoteListView = (ListView) findViewById(R.id.listview_activity_main); quoteListView.setAdapter(quoteArrayAdapter); } }
In Zeile 18 legen wir die Membervariable mQuoteList an. Die Variable besitzt den Datentyp List und kann mehrere Quote-Objekte in sich aufnehmen. Wir werden sie von nun an als Datenquelle für unseren ListView verwenden und in ihr die auszugebenden Zitate speichern.
Die nächste Änderung nehmen wir an der createQuoteList() Methode vor. In den Zeilen 33 und 34 lassen wir ein Quote-Objekt erzeugen und fügen es der ArrayList mQuoteList als erstes Element hinzu. Für das Erzeugen eines Quote-Objekts übergeben wir dem Konstruktor den Zitattext, den Autorennamen und die Bild-ID. Dem Autor Johann Wolfgang v. Goethe haben wir die ID goethe zugewiesen. Den Zitattext lesen wir aus dem Array sampleQuotes aus, in welchem wir in der vorherigen Lektion mehrere Zitattexte gespeichert hatten.
Mit den Zeilen 36-44 fügen wir der Datenquelle weitere Quote-Objekte hinzu. Dabei übergeben wir die Referenz auf das jeweils erstellte Quote-Objekt direkt der add() Methode. Insgesamt fügen wir auf diese Weise der mQuoteList neun weitere Elemente hinzu, so dass sie nun zehn Quote-Objekte in sich aufgenommen hat.
In Android Studio sollte der Inhalt der MainActivity.java
Klassendatei nun wie folgt aussehen:
In der oberen Abbildung ist die überarbeitete MainActivity.java
Klassendatei dargestellt. Es wurden an zwei Stellen Änderungen vorgenommen.
Zuerst wurde die Instanzvariable mQuoteList (Markierung A) angelegt, sie wird uns von nun an als ListView-Datenquelle dienen. Anschließend wurden in der createQuoteList() Methode zehn Quote-Objekte erzeugt und der ArrayList mQuoteList hinzugefügt (Markierung B).
Wir haben nun des Datenmodell und auch eine neue Datenquelle für den ListView unserer Android App erstellt. Als letzten Schritt müssen wir nun die neue Datenquelle über einen ArrayAdapter mit dem ListView verbinden.
3. Verbinden des ListViews mit der Datenquelle
Unseren ListView haben wir bereits in der vorherigen Lektion mit einem normalen ArrayAdapter verbunden. Dieser Adapter versorgt den ListView bisher mit Daten aus einer String-Datenquelle, eine mit String-Objekten gefüllte ArrayList.
Wir werden nun den bereits existierenden ArrayAdapter so anpassen, dass er aus der neuen Datenquelle die, für den ListView erforderlichen, Inhalte extrahieren kann. Dazu sind zwei Änderungen in der bindAdapterToListView() Methode notwendig.
Im unteren Quellcode sind die beiden erforderlichen Änderungen bereits durchgeführt worden:
An dieser Stelle endet der freie Inhalt dieser Lektion. Wir hoffen, sie hat dir bis hierher gefallen! Du kannst sie im geschützten Bereich von ProgrammierenLernenHQ fortsetzen, in welchem sich alle Lektionen unserer Android Online-Kurse befinden.
Unsere Android Kurse bestehen aus insgesamt 43 großen Lektionen und sind unterteilt in 13 frei zugängliche und 30 Premium-Lektionen. Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer unseres Android Online-Kurs Gesamtpaket zugänglich.
In unserem Android Online-Kurs Gesamtpaket befinden sich 43 große Lektionen, in denen wir dir schrittweise zeigen, wie voll funktionstüchtige Android Apps programmiert werden.
Diese Lektion ist Teil unseres Android Gesamtpakets. Insgesamt sind unsere Online-Kurse unterteilt in 13 frei zugängliche und 30 Premium-Lektionen.
Die Premium-Lektionen befinden sich in dem geschützten Bereich und sind nur für Käufer des Android Online-Kurs Gesamtpakets zugänglich.
Welche Inhalte befinden sich im Android Online-Kurs Gesamtpaket?
Wir hoffen, Dich bald als neuen Kursteilnehmer unserer Android Online-Kurse begrüßen zu dürfen!
Einmal kaufen und dadurch zeitlich unbegrenzten Zugriff auf alle Inhalte unseres Android Online-Kurs Gesamtpakets erhalten.
Hinweis: Der untere Quellcode ist Teil des geschützten Bereichs von ProgrammierenLernenHQ. Durch Freischalten unserer Android Online-Kurse erhältst du Zugriff auf alle geschützten Inhalte.
Erfahre mehr über unsere Android Online-Kurse.
In Zeile 2 haben wir den konkreten Typ des ArrayAdapters (innerhalb der spitzen Klammern angegeben) von String auf Quote geändert. Der ArrayAdapter quoteArrayAdapter kann dadurch nur noch mit einer Datenquelle (hier ArrayList) verbunden werden, die Quote-Objekte in sich aufgenommen hat.
Hinweis: Die Variable quoteArrayAdapter ist somit eine Instanz der generischen Klasse ArrayAdapter mit dem konkreten Typargument Quote. Somit kann dieser ArrayAdapter nur mit Quote-Objekten umgehen.
In Zeile 7 verbinden wir den ArrayAdapter mit der neuen Datenquelle mQuoteList. Diese enthält zehn Quote-Objekte. Die vorherige Datenquelle mSampleQuoteList, welche String-Objekte enthielt, wird nun nicht mehr benötigt. Wir lassen sie jedoch weiter als Membervariable in unserem Quellcode bestehen.
Um die beiden eben beschriebenen Änderungen am Quellcode durchzuführen, öffnen wir die Klassendatei MainActivity.java
im Editor von Android Studio. Dazu klicken wir doppelt auf ihren Dateinamen im Project Tool Window. Die Klassendatei befindet sich im Package-Ordner de.codeyourapp.zitate unseres Projekts.
Im unteren Quellcode der MainActivity.java
Datei wurden die beiden Änderungen bereits durchgeführt und sind grau markiert:
Außer an den Zeilen 48 und 53 müssen keine weiteren Änderungen vorgenommen werden.
Der ArrayAdapter kann nun Quote-Objekte aus der angeschlossenen Datenquelle extrahieren und verarbeiten. Da es sich um einen normalen also um keinen angepassten ArrayAdapter handelt, kann er die extrahierten Daten dem verbundenen ListView nur als String-Inhalte weitergeben. Dafür nutzt er automatisch die toString() Methode der Quote-Klasse.
Die toString() Methode erzeugt aus dem Zitattext, Autorennamen und der Bild-ID eine Zeichenkette und liefert diese an den Aufrufer (den ArrayAdapter) zurück. Der ArrayAdapter füllt mit dieser zusammengesetzten Zeichenkette den TextView mit der ID R.id.quote_text, der später für die Ausgabe des Zitattexts verwendet wird.
Auf diese Weise wird für jedes in der Datenquelle enthaltene Quote-Objekt eine ListView-Zeile vom ArrayAdapter erstellt. Für jede Zeile wird der TextView mit der ID R.id.quote_text mit einer zusammengesetzten Zeichenkette, welche die Inhalte des entsprechenden Quote-Objekts enthält, gefüllt. Dadurch können wir sehr einfach die Funktion des Datenmodells und des ArrayAdapters überprüfen.
In Android Studio sollte der Inhalt der MainActivity.java
Klassendatei nun wie folgt aussehen:
In der oberen Abbildung ist die vollständig überarbeitete MainActivity.java
Klassendatei dargestellt. Der Quellcode wurde an insgesamt drei Stellen überarbeitet. Welche Bedeutung die jeweilige Änderung besitzt, ist in der unteren Liste angegeben:
- A – Anlegen der Membervariable mQuoteList, die Quote-Objekte in sich aufnimmt und uns als Datenquelle dient.
- B – Erzeugen von zehn Quote-Objekten und befüllen der Datenquelle (mQuoteList) mit ihnen.
- C – Anpassen des ArrayAdapters. Ändern des konkreten Typs des ArrayAdapters von String auf Quote, so dass der Adapter nun Quote-Objekte verarbeiten kann. Zuweisen der neu angelegten Datenquelle mQuoteList, die den Adapter mit Quote-Objekten versorgt.
Wir haben nun den ListView über den ArrayAdapter mit der neuen Datenquelle verbunden. Wenn der ListView von nun an neue Zeilen anfragt, wird der mit ihm verbundene ArrayAdapter die dafür benötigten View-Elemente erstellen. Der Adapter wird die dazu erforderlichen Inhalte aus der mit Quote-Objekten gefüllten Datenquelle extrahieren.
Wie dies zur Laufzeit auf einem Android Gerät aussieht, werden wir im nächsten Abschnitt erfahren, wenn wir unsere Android App im Emulator auf einem Android Virtual Device ausführen und den ListView im Normalbetrieb testen.
4. Ausführen und Testen unserer Android App
Wir werden nun unserer Android App auf einem Android Virtual Device im Emulator ausführen lassen. Auf diese Weise können wir das Aussehen und Verhalten des ListViews direkt in unserer App betrachten.
Unsere App starten wir dazu wie gewohnt über den Run > Run 'app' Menüeintrag, den wir über die obere Menüleiste erreichen.
Auf dem virtuellen Gerät sieht unsere Android App nun wie folgt aus:
In der oberen Abbildung ist der Startbildschirm, die Start-Activity, unserer App dargestellt. Er besteht nun aus einem Button und dem ListView. Die Zeilen des ListViews werden nach den Vorgaben des Zeilenlayouts erstellt, welches wir in einer vorherigen Lektion definiert haben. Sie bestehen jeweils aus drei View-Elemente, ein ImageView und zwei TextViews.
Die vier bereits dargestellten ListView-Zeilen wurden vom ArrayAdapter erstellt. Dazu hat er aus der verbundenen Datenquelle jeweils ein Quote-Objekt extrahiert und dessen toString() Methode aufgerufen. Den zurückerhaltenen String hat der Adapter anschließend als Inhalt für den oberen TextView der jeweiligen Zeile verwendet.
Wenn wir die Liste auf dem Android Gerät nach unten scrollen, werden uns weitere Zitate angezeigt. Dazu fordert der ListView beim mit ihm verbundenen ArrayAdapter die darzustellenden neuen Zeilen an. Der Adapter extrahiert dann aus der mit ihm verbundenen Datenquelle, die mit Quote-Objekten gefüllte ArrayList, die benötigten Inhalte und befüllt mit diesen die zugehörigen View-Elemente des Zeilenlayouts.
Da wir momentan nur einen normalen ArrayAdapter verwenden, wird nur das obere TextView-Element einer jeden Zeile mit extrahierten Inhalt gefüllt. Die beiden anderen View-Elemente bleiben unverändert, da für das Autorenbild und den Autorenname momentan noch keine Daten vom ArrayAdapter aus der Datenquelle extrahiert werden können.
Dies werden wir in der nächsten Lektion ändern, wenn wir einen angepassten ArrayAdapter implementieren, der gezielt Inhalte aus der Datenquelle extrahieren kann und diese an das jeweils passende View-Element des Zeilenlayouts weiterreicht.
Zusammenfassung
In dieser Lektion haben wir das Datenmodell für die Zeilen des ListViews definiert. Dazu haben wir die Java-Klasse Quote.java
angelegt. Mit Hilfe dieser Klasse werden die auszugebenden Inhalte der ListView-Zeilen gespeichert. Sie ist daher dem Zeilenaufbau des ListViews nachgebildet.
Anschließend haben wir einige Quote-Objekte erzeugt und mit ihnen eine ArrayList gefüllt, welche uns im weiteren Verlauf dieses Kurses als Datenquelle dienen wird.
Diese Datenquelle haben wir danach über einen normalen ArrayAdapter mit dem bereits integrierten ListView verbunden. Die Aufgabe des Adapters ist es, die Quote-Objekte aus der Datenquelle zu extrahieren und deren Inhalte dem Zeilenlayout, also den Zeilen des ListViews, zuzuweisen. Abschließend haben wir unsere Android App im Emulator auf einem Android Virtual Device ausgeführt und die korrekte Funktionsweise unseres Datenmodells und des ListViews überprüft.
Wir haben dadurch den dritten großen Schritt für das Verbinden von Daten und Benutzeroberfläche getan, indem wir ein eigenes Datenmodell für unseren ListView implementiert haben. In der nächsten Lektion werden wir mit unserem Vorhaben fortfahren und dazu die vierte und letzte Maßnahmen umsetzen:
-
Erstellen eines angepassten ArrayAdapters – Die mit Hilfe des Datenmodell angelegten Zitate-Objekte können bisher nur textuelle dargestellt werden. Damit jedes Element eines Zitats an der richtigen Postion in der ListView-Zeile ausgegeben wird, erstellen wir einen angepassten ArrayAdapter, der die hinterlegten Daten mit dem Zeilenlayout des ListViews verbindet. Was dies genau bedeutet, erklären wir ausführlich in der zugehörigen Lektion.
Somit sind wir am Ende dieser Lektion angelangt. Es wurde ein eigenes Datenmodell erstellt, welches den Aufbau der ListView-Zeilen nachbildet. Auf Basis dieses Datenmodells wurde eine neue Datenquelle angelegt und über einen normalen ArrayAdapter mit dem ListView verbunden.
In der nächsten Lektion werden wir nun einen angepassten ArrayAdapter implementieren, der alle drei View-Elemente der ListView-Zeilen mit Inhalten aus der angeschlossenen Datenquelle versorgt.