天天看點

GWT筆記(4)

版權聲明:本文為部落客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::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方法,但還是該留意它,或許用得上。