Automatischer Viewer Refresh

Automatischer Update eines Labelproviders

In der aktuellen Ausgabe des Eclipse-Magazins gibt es einen Artikel zum Thema Databinding,
soweit war darin für mich nicht viel neues, eines allerdings hat mich sehr gefreut, und das
wusste ich bisher nicht.

Es gibt eine Möglichkeit, einen Viewer automatisch updaten zu lassen, wenn sich eine Property im Modell ändert.
Ich hatte das bisher immer manuell (prinzipiell über ValueChangeListener) gelöst.

Was der Autor in diesem Artikel vorstellt ist der ObservableMapLabelProvider.
Dieser Labelprovider assoziiert eine Modellobjekt mit einer Property.
Als Key in der „Map“ (es ist nicht wirklich eine) wird das beobachtete Modellobjekt und zusätzlich ein PropertyDescriptor
gespeichert. Ein Aufruf von getValue() liefert das entsprechende Attribut für den Descriptor.

Der Labelprovider wird mit einer ObservableMap im Konstruktor erzeugt. Dieser registriert einen MapChangeListener
auf die Map, so dass Änderungen hierbei sofort registriert werden.

Das ganze sieht in einfachem COde für einen TableViewer ungefähr so aus:

ObservableListContentProvider cp = new ObservableListContentProvider();
viewer.setContentProvider(cp);
IObservableMap[] map = BeansObservables.observeMaps(cp
.getKnownElements(),
new String[] { „name“, „vorname“, „email“ });
viewer.setLabelProvider(new ObservableMapLabelProvider(map));
viewer.setInput((DomainUtil.getDemoData()));

Interessant hierbei ist die Zeile BeansObservables.observeMaps(cp
.getKnownElements(),
new String[] { „name“, „vorname“, „email“ });

Die Parameter hier sind eine ObservableSet von zu beobachtenden Objekten sowie die Attribute die hierbei beobachtet werden sollen.
Dies kann auch nur ein String sein statt ein String-Array.

Was hier intern passiert (man bemerke, ich arbeite mit 3.5) ist folgendes:
BeanProperties.value(propertyName).observeDetail(domain);

Was ist das jetzt?

Das ist die neue Properties-API von Galileo, dazu später mehr.

Es wird also eine Property für das zu beobachtete Attribut erzeugt, z.B. „name“ (BeanProperties.value(propertyName)),
und dieses in dem ModellObjekt überwacht (..observeDetail(domain)). Die Methode „observeDetail“ erwartet ein
ObservableSet und liefert hierfür eine Map mit den beobachteten Objekten als Keys und den entsprechenden Properties als
Values.

Woher weiß aber jetzt der Labelprovider, dass sich eine Property geändert hat?
Wenn man sich den Labelprovider anschaut passiert hier wirklich nichts anderes als das ein MapChangeListener registriert wird,
und dieser macht per se erst mal nichts anderes als das Hinzufügen und Entfernen von Elementen in einer Map zu überwachen,
was uns aber interessiert ist nicht das Hinzufügen/Entfernen, sondern dass sich ein Attribut in einem Element der Map
geändert hat, und das ist zunächst mal nicht ersichtlich, wie diese Änderung dem Labelprovider mitgeteilt wird.

Schauen wir uns das also mal genauer an:

INteressant hierbei ist die Klasse SetSimpleValueObservableMap, die die Klasse ComputedObservableMap erweitert.
Diese Klasse wird intern verwendet.

Hier findet man die Zeilen:
protected void hookListener(Object addedKey) {
if (cachedValues != null) {
cachedValues.put(addedKey, detailProperty.getValue(addedKey));
detailProperty.addListener(addedKey, listener);
}
}

DetailProperty in diesme FAll ist eine BeanValueProperty, an welche ein Listener angehängt wird, und zwar der folgende:
new ISimplePropertyListener() {
public void handlePropertyChange(
final SimplePropertyEvent event) {
if (!isDisposed() && !updating) {
getRealm().exec(new Runnable() {
public void run() {
notifyIfChanged(event.getSource());
}
});
}
}

Die Methode notifyIfChanged wiederum feuert intern ein MapChangeEvent

fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
newValue));

Und auf diese Weise kann der Labelprovider auf Änderungen innerhalb der Bean hören.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s