2021年12月17日 星期五

GWT 中 JS 與 Java GWT code 互傳資料

因為最近在 GWT 遇到很多坑,所以在此紀錄一下

使用 JS Code

根據 GWT 官方 Blog 的範例,要使用 JS Code 的話,如下:
native String flipName(String name) /*-{
	// ...implemented with JavaScript
	var re = /(\w+)\s(\w+)/;
	return name.replace(re, '$2, $1');
}-*/;
藉由native關鍵字、/*-{}*/;的語法來引用其他語言的程式碼。
JS 使用 Java code
根據官網,使用 Java method ,得以這種方式撰寫:
@{Class Name With Path}::{Method Name}(L{java/lang/String};)({Value});
例如使用
new org.example.foo.Flipper.onFlip(Object obj)
,則寫成
@org.example.foo.Flipper::onFlip(L{java/lang/Object};)(obj);
在同一 Class
這個在官網已經有範例了:
package org.example.foo;
public class Flipper {
	public native void flipName(String name) /*-{
		this.@org.example.foo.Flipper::onFlip(Ljava/lang/String;)(s);
	}-*/;

	private void onFlip(String flippedName) {
		// do something useful with the flipped name
	}
}
使用其他 class 的 method
假設有以下的 class
package org.example.client;

public class Bar {
	public void onLoad(Object data){
		// ...
	}
}

我要使用 Bar 的 onLoad 要這樣處理

public native void barLoadData(Bar b) /*-{
	var o = {}

	b.@org.example.client.Bar::onLoad(Ljava/lang/Object;)(result);
}*-/;
native method 使用其他 native method code

如果你認為 native 用 native 可以像這樣子

package org.example.foo;
public class Flipper {
	public native void flipName(String name) /*-{
	}-*/;


	public native void loadName(String name) /*-{
		this.flipName(name);
	}-*/;
}

抱歉,你只會得到 error

因為 GWT 將 Flipper 轉換成 javascript code 時, method 也會變更名稱,所以 Flipper 轉成 JS 不是

{
	flipName: function(name){/* ... */},
	loadName: function(name){
		this.flipName(name);
	},
}

而可能是

{
	Ab: function(name){/* ... */},
	Cd: function(name){
		this.flipName(name);
	},
}
要正確地讓其使用 flipName function 還是得用
@{Class Name With Path}::{Method Name}(L{java/lang/String};)({Value});
即是
package org.example.foo;
public class Flipper {
	public native void flipName(String name) /*-{
	}-*/;

	public native void loadName(String name) /*-{
		this.@org.example.foo.Flipper::flipName(Ljava/lang/String;)(name);
	}-*/;
}

使用其他 JS 變數、function

如果要使用全域變數、function,例如我有以下 function

function foo(){
	// ...
}

要使用 foo(),可能會認為 foo() 或者 window.foo() 吧。

但事實上,在 GWT 沒法這樣取得 window object,所以這兩種寫法都是錯的。在 GWT 中要使用 window object 得用變數 $wnd

所以 GWT code 應為

native void sayHelloInJava(String name) /*-{
	$wnd.sayHello(name); // $wnd is a JSNI synonym for 'window'
}-*/;

其他

關於在 HTML 頁中使用 GWT 的 method,這種狀況我還沒遇到。所以跳過

不過在官網上其實有寫,在Getting to really know GWT, Part 1: JSNI的«Using JSNI to access external JavaScript code»段落中。

參考資料

Getting to really know GWT, Part 1: JSNI. (2008, August 17). Google Web Toolkit Blog. https://webtoolkit.googleblog.com/2008/07/getting-to-really-know-gwt-part-1-jsni.html
What is the native keyword in Java for? (2020, June 10). Stack Overflow. https://stackoverflow.com/a/30635871
C. (2014, April 22). GXT – JavaScript Native Interface (JSNI callable javascript). My Blog. https://codefollow.wordpress.com/2014/04/22/gxt-javascript-native-interface-jsni/

沒有留言:

張貼留言