Wie löst ihr asynchrone Datenermittlung?

Thallius

Top Contributor
Hi,

ich habe immer wieder folgendes Szenario:

Ich habe zum Beispiel eine Klasse KundenListe. Diese Klasse enthält alle Kunden meines Betriebes. Das können natürlich gerne auch mal 100000 sein.
Sagen wir in dieser Klasse gibt es nun eine Methode getKundenIrgendwas() (Total egal was die macht) welche aber ein paar Sekunden braucht um fertig zu werden (Große Datenbank-Zugriffe etc).

Also muss ich ein Progress-Fenster aufmachen und asynchron die Daten bearbeiten.

Sagen wir die Klasse KundenController würde also die Methode getKundenIrgendwas aufrufen um an das Ergebnis zu kommen.

Damit ergeben sich 2 Fragen:

1) Wer öffnet nun das Progress-Fenster ? Der Kundencontroller oder doch besser die Kundenliste selber. Zweiteres wäre eigentlich logischer, da ich die Methode ja auch diurchaus von anderen Klassen aufrufen kann und dann müsste ich doppelten Code zum Öffnen des Fensters schreiben.

2) Wie benachrichtige ich den KundenController, dass getKundenIrgendwas() fertig ist? Klar, das sauberste wäre hier irgendeine Form von Listener aber eigentlich ist das doch totaler Overhead für fast jede Klasse auch eine zusätzliche Listenerklasse anzulegen, die dann in den meisten Fällen eh nur von einer aufrufenden Klasse benutzt wird.

Also wie löst ihr sowas?

Gruß

Claus

P.S. Das mit den Kunden ist jetzt nur ein an den Haaren herbeigezogenes Beispiel. Bitte jetzt keine Konzeptänderungen vorschlagen wie man Kunden verwaltet :)
 

Joose

Top Contributor
1) Wer öffnet nun das Progress-Fenster ? Der Kundencontroller oder doch besser die Kundenliste selber. Zweiteres wäre eigentlich logischer, da ich die Methode ja auch diurchaus von anderen Klassen aufrufen kann und dann müsste ich doppelten Code zum Öffnen des Fensters schreiben.

Schwierige Frage ... laut deiner Beschreibung hat KundenListe schon eine Liste von Kunden, aber trotzdem sind dort auch Datenbankzugriffe notwendig.
Hier finde ich fehlt noch eine Trennung zwischen "Daten halten/verwalten" und "Daten laden/speichern". -> Wäre aber schon ein kleiner Schritt zur Konzeptänderung ;)

Im Grunde würde ich aber sagen der Controller sollte entscheiden welche der Methoden er asynchron aufruft und ob dabei eben ein Fenster angezeigt werden soll, da der Controller die Logik abbilden sollte. KundenListe sollte sich nur ums verwalten kümmern.

2) Wie benachrichtige ich den KundenController, dass getKundenIrgendwas() fertig ist? Klar, das sauberste wäre hier irgendeine Form von Listener aber eigentlich ist das doch totaler Overhead für fast jede Klasse auch eine zusätzliche Listenerklasse anzulegen, die dann in den meisten Fällen eh nur von einer aufrufenden Klasse benutzt wird.

Du brauchst ja nicht für alles eine eigene Listener Klasse. Du kannst eine einfache Basisklasse (Event) anbieten welche nur mitteilt dass "getKundenIrgendwas()" fertig ist. Eine Ableitung davon könnte genauere Informationen beinhalten. Und genauso eben auch einen BasisListener welcher einfach nur die Basis Informationen verarbeitet, oder ein spezieller Listener.
 

Baldur

Aktives Mitglied
Eine Möglichkeit wäre z.B., daß du dir eine generische Klasse "LoadingTask" o.ä. schreibst, der du deine "Aufgabe" sowie einen Consumer übergibst.

Das kann etwa so aussehen
Java:
class LoadingTask<T> {
    public LoadingTask(Supplier<T> supplier, Consumer<T> consumer) {
        new Thread(() -> {
            // loading UI öffnen
            T data = supplier.get();
            // loading UI schließen
            consumer.accept(data);
        }).start();
    }
}

new LoadingTask<Kunden[]>(
    () -> return MyDataBase.loadKundenDaten(),
    (Kunden[] kunden) -> new KundenUI(kunden)
);

Somit brauchst du jeweils bloß eine Funktion, die dir ein Kunden-Array zurückgibt und eine Funktion, die das Array entgegen nimmt und in die UI packt. Die generische LoadingTask Klasse startet dann einen Thread, in dem die Daten geladen werden und es am Ende an deinen Consumer übergibt.
Das Beispiel ist jetzt Java8, aber klappt im Prinzip auch in älteren Versionen, nur dann ohne Lambdas und du musst dir eigene Interfaces anlegen ;)
 

Thallius

Top Contributor
Du brauchst ja nicht für alles eine eigene Listener Klasse. Du kannst eine einfache Basisklasse (Event) anbieten welche nur mitteilt dass "getKundenIrgendwas()" fertig ist. Eine Ableitung davon könnte genauere Informationen beinhalten. Und genauso eben auch einen BasisListener welcher einfach nur die Basis Informationen verarbeitet, oder ein spezieller Listener.

Die Idee mit der Basisklasse finde ich gut. Darauf bin ich noch gar nicht gekommen. Manchmal liegt das einfache halt doch näher als man denkt :)

Gruß

Claus
 

Thallius

Top Contributor
Kann man in Java bei einer Klasse auch angeben, dass eine Methode überschrieben werden muss wenn von dieser Klasse abgeleitet wird?

Gruß

Claus
 

Ähnliche Java Themen

Neue Themen


Oben