Как обернуть обратный вызов, используя типы оверлея JavaScript (GWT)? - PullRequest
6 голосов
/ 07 марта 2012

В классе Экранный объект у меня есть все завернутые, кроме событий. Я не могу не понять шаблон и действительно нужен пример.

В JavaScript вы создаете обратный вызов для объекта следующим образом:

displayObject.onPress = function(event) {
    $wnd.alert("object pressed");
}

Я обернул параметр Mouse Event :

public class MouseEventImpl extends JavaScriptObject {
    protected MouseEventImpl() {}

    public static native MouseEventImpl create(String type, int stageX, int stageY, DisplayObjectImpl target, JavaScriptObject nativeEvent) /*-{
        return new $wnd.MouseEvent(type, stageX, stageY, target, nativeEvent);
    }-*/;

    ...other methods excluded...
}

public class MouseEvent {
    private MouseEventImpl impl;

    public MouseEvent(String type, int stageX, int stageY, DisplayObject target, JavaScriptObject nativeEvent) {
        this.impl = MouseEventImpl.create(type, stageX, stageY, target.getOverlay(), nativeEvent);
    }

    ...other methods excluded...
}

Экранный объект использует тот же шаблон наложения. Как я могу написать обратный вызов в Java и передать его в JSO? Пожалуйста, приведите пример, если можете. :)

1 Ответ

7 голосов
/ 08 марта 2012

Редактирование перед публикацией: я написал этот ответ, не пытаясь понять, почему вы пытались сделать это, предполагая, что вы использовали какое-то не-браузерное событие, которое уже перенесено довольно приятно, и если вам нужно больше данных из экземпляра NativeEvent, вы можете написать методы JSNI в ваших собственных классах, чтобы получить к нему доступ, или создать дополнительный подкласс NativeEvent, чтобы добавить больше методов и .cast() в ваш класс. Добавьте обработчик в виджет, используя метод Widget.addDomHandler и соответствующий подкласс MouseEvent, чтобы получить экземпляр типа.


В JavaScript обратные вызовы - это просто функции, которые будут вызываться, когда что-то происходит. Если специально не указано, куда они передаются, они обычно будут вызываться в глобальном контексте, а не в конкретном экземпляре объекта.

var callback = function() { alert("callback called!"); };

// later, in something that consumes that callback:
callback();

Чтобы вызвать функцию в экземпляре (то есть сделать ее вызовом метода), можно обернуть этот вызов в функцию, которая не нуждается в экземпляре:

var obj = {};
obj.name = "Me";
obj.whenSomethingHappens = function() {
    alert("my name is " + this.name);
};

// wont work, so commented out:
//var callback = obj.whenSomethingHappens;

// instead we wrap in a function
// this is making a closure (by closing over obj)
var callback = function() {
    obj.whenSomethingHappens();
};

// later, in something that consumes that callback:
callback();

В Java нельзя ссылаться конкретно на метод (без отражения), а только на экземпляры объекта. Самый простой способ создать простой обратный вызов - это реализовать интерфейс, а код, который принимает обратный вызов, получает экземпляр интерфейса и вызывает определенный метод.

GWT объявляет интерфейс Command для функций с нулевым аргументом и универсальный интерфейс Callback<T,F> для случаев, которые могут пройти или потерпеть неудачу, с одним общим аргументом для каждой опции. Большинство обработчиков событий в GWT просто определяют один метод с конкретными данными, передаваемыми в этот метод.

Нам нужно использовать все эти знания, чтобы передать экземпляры Java с вызываемой функцией в JavaScript и убедиться, что они вызываются в нужном экземпляре. Этот пример - функция, которая принимает экземпляр Callback и, используя JSNI, оборачивает вызов JS.

// a callback that has a string for either success or failure
public native void addCallback(Callback<String, String> callback) /*-{
    var callbackFunc = function() {
        // obviously the params could come from the function params
        callback.@com.google.gwt.core.client.Callback::onSuccess(Ljava/lang/String;)("success!");
    };
    doSomethingWith(callbackFunc);//something that takes (and presumably calls) the callback
}-*/;

Еще один последний момент - чтобы правильно обрабатывать и планировать ошибки в GWT, важно обернуть вызов обратно в java в $ entry - эта последняя строка должна действительно быть

    doSomething($entry(callbackFunc));
...