二、JavaScript Native Interface
JavaScript本地接口JSNI。
1)聲明一個本地方法
在JSNI中聲明一個本地方法時,使用Java的標准native關鍵字,就像在JNI(Java Native Interface)中一樣。在JNI中,本地C代碼是一個單獨的文件,獨立編譯且在運行時動態加載。
在JSNI中,本地JavaScript代碼用一種特殊的注釋格式直接嵌入到Java源代碼中。
JSNIProject/src/com/xyz/client/Alert.java
--------------------------------------
public class Alert{
public static native void alert(String msg) /*-{
$wnd.alert(msg);
}-*/;
}
--------------------------------------
JSNI注釋塊以“/*-{”開頭,以“}-*/”結束。
這個例子顯示,當用JSNI訪問瀏覽器窗口和文檔對象時,必須分別用$wnd和$doc引用它們。在嵌套的框架中運行已編譯的腳本時,$wnd和$doc會自動的初始化,用主機頁窗口和文檔來代替框架。
2)它的工作機制
在WEB模式中,GWT編譯器把客戶端一半的Java程序轉換成JavaScript。
正常情況,當編譯器看到方法聲明時,其括號內部的代碼必須經歷解釋過程。如果方法是本地方法,編譯器處理更為簡單。它直接復制JavaScript本地代碼到已編譯的結果中。
一旦JavaScript被解釋后,JavaScript代碼中的任何錯誤就只能在運行時才能發現。
3)從Java中調用JSNI
在Java中調用JSNI與調用其它Java方法沒有什么不同。
JSNIProject/src/com/xyz/client/LSNIExample.java
--------------------------------------
button1.addClickListener(new ClickListener(){
public void onClick(Widget sender){
Alert.alert("Clicked!");
}
});
--------------------------------------
4)從JSNI中調用Java
假定你傳遞一個對象到JSNI方法,你需要訪問一個字段或在對象中調用一個方法。你還需知道GWT編譯器怎樣弄糟Java域和方法名,因此你可以在JavaScript代碼中訪問它們。
(1)訪問Java域(field)
訪問Java域的語法如下:
--------------------------------------
obj.@class::field
--------------------------------------
obj 是引用對象的實例
class 是具有full-qualified的類
field 訪問域的域名
(2)調用Java方法
調用Java方法的語法和訪問Java域的語法相似,語法如下:
--------------------------------------
obj.@class::method(sig)(args)
--------------------------------------
method 調用方法的方法名
sig 內部的Java方法簽名
args 方法傳遞的參數列表
(3)方法簽名(Method Signature)
JSNI方法簽名確切地說和JNI方法簽名一樣,除了方法返回類型有所不同。
下面的表顯示了這些方法簽名
--------------------------------------
Type Signature Java Type
--------------------------------------
Z boolean
B byte
C char
S short
I int
J long
F float
D double
[type type()
Lfully-qualified-class; fully-qualified-class
--------------------------------------
例如:Java方法:
long f(int n, String s, int[] arr);
有如下的類型簽名:
ILjava/lang/String;[I)
(4)例子
下面的代碼顯示了通過JSNI訪問Java域和方法的例子。它說明了傳遞數字、字符串、布爾型和Java對象到JavaScript。它還顯示了JavaScript方法怎樣調用傳遞過來的Java對象。
--------------------------------------
Java類型 它是怎樣出現在JavaScript代碼中的
a Java numeric primitive var x=42;
String var s="my string";
boolean var b=true;
JavaScriptObject 從JavaScript代碼中初始化,典型的是作為其它JSNI方法的返回值
Java Object 通過特殊語法得到的不透明的值
--------------------------------------
JSNIProject/src/com/xyz/client/j2js.java
----------------------------------------------------------
public class J2JS{
/** Pass a Java numeric primitive */
public static void testJ2JSNumeric(){
int x=42;
jsNumeric(x);
}
privae static native void jsNumeric(int x)/*-{
$wnd.alert("x is "+x);
}-*/;
/** Pass a Java String */
public static void testJ2JSString(){
String s="my string";
jsString(s);
}
private static native void jsString(String s) /*-{
$wnd.alert("s is "+s);
}-*/;
/** Pass a boolean */
public static void testJ2JSBoolean(){
boolean b=true;
jsBoolean(b);
}
private static native void jsBoolean(boolean b) /*-{
$wnd.alert("b is "+b);
}-*/;
/** Pass an arbitrary Java Object */
public static void testJ2JSObject(){
MyJavaObject obj=new MyJavaObject();
jsObject(obj);
}
private static native void jsObject(MyJavaObject obj) /*-{
$wnd.alert("Calling getText():"+obj.@MyJavaObject::getTextAt(I)(3));
}-*/;
}
----------------------------------------------------------
如果你看GWT的源碼時,可以看到許多安裝JSNI定義的東東。大多數GWT編程者不需要定義JSNI方法,但還是該留意它,或許用得上