版權聲明:本文為部落客chszs的原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/chszs/article/details/1701720
GWT筆記(4)
一、History and Bookmarks
書簽對于Ajax應用來說是一個特殊的問題,因為使用者隻和單個的頁面進行互動,是以這兒存在許多不同的片段、狀态。GWT解決了這些問題。
處理傳回按鈕和使用者儲存有用的标簽的秘密是曆史辨別。
曆史辨別僅僅是一個字元串,用于儲存你想儲存的狀态。Google沒有記載曆史辨別的最大長度,但是推薦為在100個字元以内。
要通過程式設計來改變曆史辨別,可以調用方法:History.newItem(),History.back(),History.forward()。
如果一個使用者用web anchor把一個URL作為書簽,當重載那些頁面時,GWT将把anchor作為一個曆史辨別。它會傳遞辨別到listener,不用知道它是怎樣處理的。如果你想改變狀态,可使用Hyperlink類來代替。
在内部,曆史是通過一個特殊的标簽<iframe>來管理的。GWT腳手架腳本自動地為你加入:
HistoryProject/src/com/xyz/public/HistoryExample.html
--------------------------------------
<!-- OPTIONAL: include this if you want history support -->
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0">
</iframe>
浏覽器的“傳回”和“向前”按鈕簡單地儲存你通路過的一堆URL。通過在應用程式中進行設定,GWT使它和曆史辨別保持一緻。
下面的例子顯示了怎樣處理初始化辨別,建立事件監聽,處理事件。
HistoryProject/src/com/xyz/client/HistoryExample.java
public class HistoryExample implements EntryPoint, HistoryListener{
private Label lbl=new Label();
public void onModuleLoad(){
//Create three hyperlinks that change the application's history.
Hyperlink link0=new Hyperlink("link to foo","foo");
Hyperlink link1=new Hyperlink("link to bar","bar");
Hyperlink link2=new Hyperlink("link to baz","baz");
//If the application starts with no history token, start it
// off in the 'baz' state.
String initToken=History.getToken();
if(initToken.length()==0)
initToken="baz";
//onHistoryChanged() is not called when the application first
//runs. Call it now in order to reflect the initial state.
onHistoryChanged(initToken);
//Add widgets to the root panel.
Panel panel=new VerticalPanel();
panel.add(lbl);
panel.add(link0);
panel.add(link1);
panel.add(link2);
RootPanel.get().add(panel);
//Add history listener
History.addHistoryListener(this);
}
public void onHistoryChanged(String historyToken){
lbl.setText("The current history token is: "+historyToken);
}
二、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::fieldobj 是引用對象的執行個體
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方法,但還是該留意它,或許用得上。