GWT:如何将java数组传递给javascript本机方法?

时间:2014-03-04 09:16:18

标签: java javascript arrays gwt

我有一个String数组,现在我想将它传递给JSNI函数。我尝试在GWT中使用JsArrayString,但是我发现它无法直接初始化,因为它没有可见的构造函数。那么如何将我的String数组传递给JSNI函数并在我的javascript代码中使用它?代码如下所示:

public void callJSNI() {
    String[] stringArray = xxx;

    //How should I convert the array into a JSNI-readable format here?
}

private native void JSNIMethod(JsArrayString array) /*-{
    //some code to use the array in javascript
}-*/

3 个答案:

答案 0 :(得分:6)

API不提供简单的方法,您必须创建一个实用方法:

  1. 创建新的JSNI数组
  2. 迭代Java数组的参数并填充JSNI数组
  3. 这样的事情:

    public static JsArrayString toJsArray(String[] input) {
        JsArrayString jsArrayString = createEmptyJsArrayString();
        for (String s : input) {
            jsArrayString.push(s);
        }
        return jsArrayString; 
    }
    
    private static native JsArrayString createEmptyJsArrayString() /*-{
        return [];
    }-*/;
    

    正如OP建议的那样,我们当然可以跳过本机初始化并使用JsArrayString.createArray()

    现在我们可以摆脱本机初始化,因此我们的代码简化为:

    public static JsArrayString toJsArray(String[] input) {
    JsArrayString jsArrayString = JsArrayString.createArray().cast();
        for (String s : input) {
            jsArrayString.push(s);
        }
        return jsArrayString; 
    }
    

答案 1 :(得分:5)

Eliran Malka的答案是一个很好的起点。但请注意,在某些情况下,存在一种更有效的扩展解决方案。这就是我创建另一个答案的原因。

简单的解决方案就是:

public static JsArrayString toJsArray(String[] input) {
    JsArrayString jsArrayString = JsArrayString.createArray().cast();
    for (String s : input) {
        jsArrayString.push(s);
    }
    return jsArrayString; 
}

扩展/更有效的解决方案需要一些背景知识......

当Java代码使用Java数组时,GWT编译器使用JS数组。所以在这种情况下你已经有了一个JS数组。但这可能导致副作用,导致Dev和Prod模式中的不同行为:

由于我们在开发模式下拥有真正的Java数组,因此始终需要通过复制值来转换为JS数组。其中一个数组中的操作对另一个数组不可见。

在Prod模式下,如果我们直接使用Java数组作为JS数组,我们只会有一个数组。因此,Java或JS代码中的操作会影响另一个世界。

但如果以下内容适用于您的用例,则可以使用该数组而无需创建另一个数组:

  • 其中一个陈述必须是真实的
    • JS代码根本不会操纵数组
    • 在将Java代码提供给JSNI方法之后,Java代码不会使用该数组
  • 其中一个陈述必须是真实的
    • 该数组仅在JS代码中使用过一次(JS代码不会创建超出本机方法调用的数组的引用)
    • 在本机调用之后,Java代码不会操纵该数组。

在这种情况下,您不会产生副作用(Dev和Prod模式下的不同行为),并且数组可以直接在本机代码中使用。

这种实现包含在GWT的JsArrayUtils中。但不幸的是,目前没有String数组的实现。但实现将如下所示:

public static JsArrayString readOnlyJsArray(String[] array) {
    if (GWT.isScript()) {
        return arrayAsJsArrayForProdMode(array).cast();
    }
    JsArrayString dest = JsArrayString.createArray().cast();
    for (int i = 0; i < array.length; ++i) {
        dest.push(array[i]);
    }
    return dest;
}
private static native JavaScriptObject arrayAsJsArrayForProdMode(Object array) /*-{
    return array;
}-*/;

答案 2 :(得分:1)

最后我自己找到答案。

可以使用JsArrayString“启动”JsArrayString.createArray(),然后您就可以在javascript中执行任何操作。