Hallo,
da ich mich nun schon etwas länger mit dem GWT beschäftige und es mich ein wenig nervt, dass man immer ein AsyncCallback-Objekt nutzen muss, dass man den Ajax-Request auswerten kann, dachte ich, dass es auch eine Möglichkeit geben sollte, dass man mit bestimmten Antworten Funktionen diverser Klassen aufruft.
Derzeit habe ich es so, dass ich ein zentrales AsyncCallback-Objekt habe, was die Nachrichten empfängt. Die Nachrichten selber sind so nach der Art des Bayeux-Protokolls aufgebaut. Nur das ich halt den channel habe und dahinter ein Eventname. Sagen wir zb. den channel "/game/chat" und die Funktion "join". Das würde dann halt in der Nachricht nach "/game/chat/join" ausschauen. Nun kann ich diverse Objekte an den Channel "/game/chat" registrieren und innerhalb dieser Klasse kann ich dann noch für die eizelnen Funktionen die dazugehörigen Prozeduren definieren, welche dann aufgerufen werden, wenn die Funktion auftritt.
Nun kommt aber das eigentliche Problem. Ich hab in der Klasse (von der werden die anderen alle abgeleitet) die Membervariable:
Java:
protected JavaScriptObject eventFunctions = JavaScriptObject.createObject();
Damit kann ich dann mittels JSNI auf dieses assoziative Array direkt zugreifen mittels:
Java:
[email protected]::eventFunctions;
Die Klasse ResponseHandler zeigt sozusagen meinem Script an, dass diese Klasse asynchrone Antworten verarbeiten kann. Dafür gibt es dann die Funktion doRequest:
Java:
public native void doRequest(String eventName, ResponseHolder response) /*-{
var functions = [email protected]::eventFunctions;
if(functions[eventName] != null)
functions[eventName](response);
}-*/;
Die Klasse ResponseHolder ist einfach nur ein Interface, welches angibt, dass diese Klassen serialisierbar sind und sozusagen die eigentlich Antwort enthalten.
Nun habe ich aber bei dem GWT noch nicht richtig durchgeblickt, wie ich denn Funktionen als Parameter übergeben kann, damit ich die Funktion an dem bestimmten Event hängen kann. Oder einfacher: Wie ich die Funktion in das assoziative Array rein bekomme. Meine derzeitige Lösung sieht folgendermaßen aus:
Java:
public native void initializeEventHandlers() /*-{
var eventArray = [email protected]::eventFunctions;
eventArray["ontest"] = [email protected]::onTest(Lnet/client/gwt/ResponseHolder;
eventArray["onclear"] = [email protected]::onClear(Lnet/client/gwt/ResponseHolder;
}-*/;
Diese Funktion ist in der Klasse ResponseHandler abstrakt und muss sozusagen von jeder abgeleiteten Klasse definiert werden. Nun sieht das nicht wirklich schön aus und ist zudem noch unleserlicher. Ich hätte am Liebsten:
Java:
public native void initializeEventHandlers() /*-{
var addHandler = [email protected]::addHandler(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;);
addHandler("ontest", [email protected]::onTest(Lnet/client/gwt/ResponseHolder);
addHandler("onclear", [email protected]::onClear(Lnet/client/gwt/ResponseHolder);
}-*/;
Sieht zwar im ersten Moment nicht wirklich besser aus, aber man kann die Funktion an einer zentralen Stelle ändern. Nun weiß ich aber nicht, was ich für nen Parametertyp für eine Funktion nehmen muss. Ich hatte es mal mit http://google-web-toolkit.googlecode.com/svn/javadoc/1.4/com/google/gwt/core/client/JavaScriptObject.html versucht, aber da meinte dann das Javascript, dass der Parameter undefiniert ist.
Hat da irgendwer ein Lösungsansatz oder muss ich leider Gottes bei meiner uneleganten Lösung bleiben? Hoffe jemand hat schon ein wenig GWT-Erfahrung
Edit: Achja am liebsten wäre mir die Möglichkeit mit Annotations die Funktionen zu bestimmen, aber ich glaube da würde ich nicht drum herum kommen, dass ich die Datei vorher in Bytecode übersetze und dann PArse und dann im Endeffekt die dazugehörige Funktion erstelle, die dann nochmal übersetzt werden müsste oder? Hab mir den Compiler vom GWT noch nciht angeschaut und das würde sicher auch Monate dauern, bis ich da ne Extension fertig habe ;)