来自Javascript的WebView回调

6
我尝试创建一个简单的示例,演示从Javascript到Java的回调,基于WebEngine javadoc中的最后一个示例从JavaScript回调到Java)。但是当我在WebView中点击链接时,Java方法没有被调用,页面消失了。
public class TestOnClick extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        try {
            final WebView webView = new WebView();
            final WebEngine webEngine = webView.getEngine();

            Scene scene = new Scene(webView);

            stage.setScene(scene);
            stage.setWidth(1200);
            stage.setHeight(600);
            stage.show();

            String webPage = "<html>\n"
                    + "    <body>\n"
                    + "        <a href=\"\" onclick=\"app.onClick()\">Click here</a>\n"
                    + "    </body>\n"
                    + "</html>";

            System.out.println(webPage);

            webView.getEngine().loadContent(webPage);

            JSObject window = (JSObject) webEngine.executeScript("window");
            window.setMember("app", new JavaApp());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    public static class JavaApp {

        public void onClick() {
            System.out.println("Clicked");
        }
    }
}

注意:当使用 webView.getEngine().getLoadWorker().exceptionProperty().addListener(...) 监控加载工作器时,我没有看到 WebView 抛出任何异常。

注意:从2.2.5开始,桥接类(在本例中为JavaApp)必须声明为public - spongebob
1个回答

6

您正在尝试在创建之前访问webview DOM模型。

将与JavaApp相关的代码包装到页面加载监听器中,以实现您的目标:

webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
    @Override
    public void changed(ObservableValue<? extends State> ov, State t, State t1) {
        if (t1 == Worker.State.SUCCEEDED) {
            JSObject window = (JSObject) webEngine.executeScript("window");
            window.setMember("app", new JavaApp());
        }
    }
});

1
这种方法会引入竞态条件,如果加载的页面需要在启动时访问某些应用程序API,因为页面JavaScript是在RUNNING -> SUCCEEDED转换发生之前执行的。 - Maxim
为了解决这个经典的并发访问问题,您可以使用任何标准方法:例如,在JS中等待变量“app”初始化。 - Sergey Grinev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接