Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从JavaScript到JavaFX的后台线程调用_Javascript_Multithreading_Javafx_Webview - Fatal编程技术网

从JavaScript到JavaFX的后台线程调用

从JavaScript到JavaFX的后台线程调用,javascript,multithreading,javafx,webview,Javascript,Multithreading,Javafx,Webview,在将JRE版本1.8.0_66迁移到1.8.0_111之后,我遇到了一个从JavaScript到JavaFX的升级调用问题 长话短说:虽然有一个正在运行的后台线程,但WebView/WebEngine拒绝进行JS到Java的调用 我使用WebView呈现从域数据模型(DM)生成的HTML内容。内容包含指定了处理程序的元素,如下所示: JS部分看起来像: function explainHeadWord(hw元素){ jsBridge.jsHandleQuery(hwmelement.inn

在将JRE版本1.8.0_66迁移到1.8.0_111之后,我遇到了一个从JavaScript到JavaFX的升级调用问题

长话短说:虽然有一个正在运行的后台线程,但WebView/WebEngine拒绝进行JS到Java的调用

我使用WebView呈现从域数据模型(DM)生成的HTML内容。内容包含指定了处理程序的元素,如下所示:


JS部分看起来像:

function explainHeadWord(hw元素){
jsBridge.jsHandleQuery(hwmelement.innerHTML);
}
函数testBridge(){
jsBridge.jsTest();
}
其中
jsBridge
是控制器的内部Java类

公共类JSBridge{
public void jsHandleQuery(字符串标题词){
日志(“jsBridge:jsHandleQuery:requested%s”,headWord);
handleQuery(headWord);
}
公共测试{
日志(“jsBridge:jsTest:test successed”);
}
}
其注入方式如下:

engine.getLoadWorker().stateProperty().addListener((可观察、旧值、新值)->{
if(newValue==Worker.State.successed){
engine.setJavaScriptEnabled(true);
JSObject window=(JSObject)engine.executeScript(“window”);
setMember(“jsBridge”,newjsbridge());
//executeScript(“jsTest()”);
//executeScript(“explainHeadWord(document.getElementsByTagName('a')[0])”;
//executeScript(“jsBridge.jsHandleQuery(document.getElementsByTagName('a')[0])”;
}
除了主DM之外,我还有一个交叉引用索引,它是从DM构建的
Map
,每次DM发生变化时,都会在后台重建该索引。第一种方法(在版本1.8.0_66上运行良好)基于ExecutorService:

private ExecutorService executor=Executors.newCachedThreadPool();
私有未来索引器=executor.submit(()->false);
...
私有void重建索引(){
执行人提交(()->{
索引器。取消(true);
索引器=执行器。提交(()->{
fullSearchIndex=getIndex();
如果(isIndexingAborted())返回false;
返回true;
});             
试一试{
if(indexer.get()){
日志(“重置索引:完成”);
updateTableView();
}            
}捕捉(中断异常e){
...             
}
});
} 
正如所料,在WebView中单击锚导致JS调用
jsBridge.jsHandleQuery(hwElement.innerHTML)
,最终在Controller中实现
handleQuery(headWord)
方法调用。但在将JRE迁移到1.8.0版之后,WebView停止响应锚单击

我调查了日志,发现注入
jsBridge
是成功的,并且执行了
窗口下面代码行中注释的测试脚本。setMember()
。单击
元素不会导致任何结果。但是如果不运行测试脚本(注释),日志中会出现以下记录:


2017-01-09T02:00:47
1483920047169
160
com.sun.webkit.WebPage
好的
com.sun.webkit.WebPage
fwkAddMessageToConsole
11
fwkAddMessageToConsole():message=TypeError:jsBridge.jsHandleQuery不是函数。(在'jsBridge.jsHandleQuery(hwmelement.innerHTML)'中,'jsBridge.jsHandleQuery'未定义),lineNumber=26,sourceId=jar:file:/…/jar.jar!/view.js
片刻之后,后台(索引)线程完成,WebView中的内容被重新加载,单击
元素再次开始响应-
jsBridge.jsHandleQuery
被执行。 索引线程执行
getIndex()
方法,该方法遍历DM并返回从DM收集到的
Map
数据。与FX应用程序线程的任何交互都不存在,WebView也不依赖于索引。替换
fullSearchIndex=getMockIndex();

私有映射getMockIndex(){
试试{
睡眠(20000);
}捕获(中断异常e){}
return Collections.emptyMap();
}
在后台,线程不会改变
的行为

下一步是利用
javafx.concurrent.Service
但结果是一样的


感谢您指出我做错了什么以及如何解决这个问题。

尝试在监听器之外实例化Bridge,即

final JSBridge bridge = new JSBridge();
engine.setJavaScriptEnabled(true);
engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue == Worker.State.SUCCEEDED) {
      JSObject window = (JSObject) engine.executeScript("window");
      window.setMember("jsBridge", bridge);
    }
});
(为我工作,从1.8.0_91迁移到1.8.0_121)