一般目标:从javascript调用一些非静态Java方法
描述:在 Java Applet 代码中查找 gwt 在 DOM 上的小部件并调用它的 java 方法(非静态(
JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject) win.getMember("document");
JSObject gwtWidget = (JSObject) doc.call("getElementsByName", widgetName);
//todo: have possibility to call `exported` java method over here, smth like:
//Object[] params = new Object[1];
//params[0] = widgetName;
//Object result = gwtWidget.call("exportedJavaMethod", params);
//todo: or just call global ($wnd) static JSNI bridge method:
//Object result = win.call("exportedJavaMethod", params);
//
问题是:我可以通过小部件的 id 而不是小部件找到,而是没有任何导出实例化方法的 DivElement。
我的小部件类是可导出的(gwt导出(:
@Export(value="somewidget")
public class SomeWidget extends SimplePanel implements ..., Exportable {
private final String id = "id_some_widget_" + count++;
private static int count = 0;
public SomeWidget () {
getElement().setAttribute("name", id);
getElement().setId(id);
}
...
public static Element getInstanceById(String elementId) {
Element someWidget= DOM.getElementById(elementId);
return someWidget;
}
public String getSomeInstancedData() {
return "useful_inner_data" + this.id;
}
因此,例如,我想找到添加到 DOM 的具体小部件,并在 javascript 中调用非静态方法getSomeInstancedData()
。可能吗?
假设像这样:
var someWidget = document.getElementById(widgetId);
alert(someWidget.getSomeInstancedData());
//or:
var someWidgetExported = com.mypackage.widgets.somewidget.getInstanceById(listenerId);
alert(someWidgetExported.getSomeInstancedData());
在基本模块中,我写:
ExporterUtil.exportAll();
有一个视图(ViewWithSomeWidget.ui.xml(包含这个小部件:
...底座:表单base:SomeWidget ui:field="someWidget" ....../base:SomeWidget...
当 SomeWidget 没有实现可导出时,项目运行良好,但我无法调用找到的小部件的 DIV 元素的非静态方法。
到那时,为了解决这个问题,SomeWidget 实现了 Exportable,但由于 ClassCastException 使用延迟绑定,progect 不能很好地显示带有 SomeWidget 的视图:
ClassCastException: com.mypackage.widgets.SomeWidgetExporterImpl cannot be cast to com.mypackage.widgets.SomeWidget
那么,可能还有其他方法可以找到小部件的javascript对象并调用其导出的java方法?无论如何,任何想法都非常受欢迎。
你可以声明一个javascript函数,它将触发非静态方法。
例如:
package com.example;
public class Layout extends VLayout() {
private String nonStaticVar = "nonStaticVar";
public Layout() {
declareMethod(this);
}
//Method which declares non-static method in javascript
public native void declareMethod(Layout layout) /*-{
var layout = layout;
$wnd.doSomething = function(someString) {
layout.@com.example.Layout::doSomething(Ljava/lang/String;)(someString);
}
}-*/;
//Non static method which is being called
public String doSomething(String someString) {
//Do something, e.g. set var in this instantiated class, or output stuff
this.nonStaticVar = someString;
Window.alert(someString);
}
}
现在,打电话 做某事("bla"(;从 JavaScript 将调用你的非静态方法。
你可以在div元素上定义一个自己的jsmethod,它可以调用widget-method
@Export(value="somewidget")
public class SomeWidget extends SimplePanel implements ..., Exportable {
private final String id = "id_some_widget_" + count++;
private static int count = 0;
public SomeWidget () {
getElement().setAttribute("name", id);
getElement().setId(id);
attachInstanceHook(getElement());
}
...
public String getSomeInstancedData() {
return "useful_inner_data" + this.id;
}
private native void attachInstanceHook(Element element) /*-{
var elem = element;
var widget = this;
elem.getWidgetData = function () {
widget.@your.package.name.SomeWidget::getSomeInstancedData()();
};
}-*/;
你的JS代码应该看起来像这样:
var someWidget = document.getElementById(widgetId); //the id of the div element
alert(someWidget.getWidgetData());
与其尝试通过其 DOM 元素获取小部件,不如先将其 Java 实例注入全局范围并引用它:
public class SomeWidget extends SimplePanel implements ..., Exportable {
//...
public SomeWidget () {
getElement().setAttribute("name", id);
getElement().setId(id);
attachToGlobalScope(id, this);
}
private native void attachToGlobalScope(String id, SomeWidget instance) /*-{
$wnd.shared[id] = instance;
}-*/;
//...
}
稍后,更新小程序 API 层中的相应提取:
JSObject win = JSObject.getWindow(this);
JSObject shared = (JSObject) win.getMember("shared");
Widget widgetRef = (Widget) shared.getMember(widgetId);
免责声明:这个有点歪曲的解决方案中继 JavaScript 全局作用域变量,这通常被认为是不好的做法,但这里充当唯一的公共作用域,因此被滥用于对象存储。