Zellbiologie: GWT CellTable

(Natürliche) Selektion

Auch für die Verwaltung einer Zeilen-Selektion bietet GWT umfangreiche Unterstützung. Zu diesem Zweck muss der Tabelle lediglich ein Selektionsmodell zugewiesen werden. Mit den Klassen SingleSelectionModel und MultiSelectionModel existieren bereits vordefinierte Implementierungen, die eine Einfach- beziehungsweise Mehrfach-Auswahl erlauben. Über Listener, die am Selektionsmodell registriert werden, kann sich eine Anwendung über Änderungen in der Selektion informieren lassen.

Der mysteriöse KeyProvider, der in Listing 3 referenziert wurde, spielt bei der Selektion eine wichtige Rolle. Er ermöglicht eine Identifikation der zu verwaltenden Datenobjekte, indem er Objekte auf eindeutige Schlüssel abbildet. Somit kann das Selektionsmodell eine Liste über die markierten Einträge führen, auch wenn durch Nachladen von Daten neue Instanzen der Datenobjekte angelegt werden. Die Implementierung eines KeyProviders ist relativ einfach. Es muss lediglich aus einem übergebenen Datenobjekt ein eindeutiges Schlüsselfeld extrahiert werden, beispielsweise der Datenbank-Primärschlüssel. Für unsere SongInfo-Datenobjekte gestaltet sich das wie folgt:

private static final ProvidesKey KEY_PROVIDER =
new ProvidesKey() {
public Object getKey(SongInfo item) {
return item.getSongID();
}
};
Symbiont – Data Provider

Nachdem nun die Oberfläche der Übersichtstabelle für Songs komplett ist, wird es Zeit, sich mit der Beschaffung der Daten zu befassen. Wie bereits erwähnt, liefert ein JPA-basierter Service Informationen über gespeicherte Songs. Der Aufruf erfolgt über GWT Remote Procedure Calls [4]. Technisch gesehen heißt das, dass es sich bei dem Service um ein Servlet handelt, das ein bestimmtes Service-Interface (Listing 4) implementiert. Clients verwenden ein davon abgeleitetes asynchrones Interface, dessen Methoden keinen Rückgabewert haben, dafür aber ein Callback-Objekt als zusätzlichen Parameter erwarten. Erfolgt ein Methodenaufruf über das asynchrone Interface, kümmert sich die GWT-Runtime im Hintergrund um die Kommunikation mit dem Server. Sobald das Ergebnis (oder auch ein Fehler) vorliegt, ruft sie eine entsprechende Methode auf dem Callback-Objekt auf.

Das Service-Interface zum Suchen von Songs besteht lediglich aus einer Methode, die eine Untermenge der vorhandenen Songs liefert. Das Ergebnisobjekt SongSearchResult enthält die Anzahl insgesamt vorhandener Songs sowie eine Liste mit den Ergebnissongs.

Listing 4
@RemoteServiceRelativePath("mediasearch")
public interface SongSearchService extends RemoteService {
SongSearchResult searchSongs(int startIdx, int count);
}

Der Aufruf des Service erfolgt nicht direkt von der UI, sondern liegt in der Verantwortung des Data Providers. Dieser ist an der Tabelle registriert und erhält Benachrichtigungen, wenn Daten angezeigt werden sollen, die bisher noch nicht geladen wurden. Er fordert die benötigten Daten dann vom Service an und schreibt sie in die Tabelle. GWT bietet bereits eine Basisklasse für eigene Provider-Implementierungen an: AsyncDataProvider. Abgeleitete Klassen müssen lediglich die Methode onRangeChanged()definieren, der eine Referenz auf das betroffene Cell Widget übergeben wird. Eine beispielhafte Implementierung zeigt Listing 5.

Listing 5
public class SongDataProvider extends AsyncDataProvider {
protected void onRangeChanged(final HasData display) {
SongSearchServiceAsync service =
GWT.create(SongSearchService.class);
final Range range = display.getVisibleRange();
service.searchSongs(range.getStart(), range.getLength(),
new AsyncCallback() {
public void onSuccess(SongSearchResult result) {
display.setRowCount(result.getSongCount());
display.setRowData(range.getStart(), result.getList());
}
public void onFailure(Throwable caught) {
// exception handling
}
});
}
}

HasData ist ein generisches Interface, das von CellTable implementiert wird. Die Provider-Implementierung ermittelt über getRange()den sichtbaren Bereich der Tabelle und fordert exakt diese Daten vom Service an – damit wird verständlich, warum der Service gerade diese Parameter erwartet. Als Callback-Objekt kommt eine anonyme Klasse zum Einsatz. Die onSuccess()-Methode wird aufgerufen, sobald der Service Ergebnisse liefert. Die Implementierung wertet das Ergebnisobjekt aus und übergibt per setRowData()die Liste mit Datenobjekten an die Tabelle. Außerdem setzt sie die Gesamtzahl der Zeilen. Das ist wichtig, damit sich die Pager-Komponente entsprechend initialisieren kann.

Die Verknüpfung zwischen CellTable und Data Provider erfolgt im Konstruktor von SongOverviewTable:

SongDataProvider provider = new SongDataProvider();
provider.addDataDisplay(cellTable);
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.