JavaFX中通过JS桥刷新WebView内容失败问题求助
AppDrawer WebView 删除快捷方式后无法刷新问题
我正在开发一款AppDrawer(一站式启动快捷方式工具),但JSCallBack桥接类中的方法在删除快捷方式后无法刷新WebView内容——后端文件已成功删除,但界面上对应的应用仍显示,无法更新。
相关代码
AppDrawerMain.java
public class AppDrawerMain extends Application { @Override public void start(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(AppDrawerMain.class.getResource("main.fxml")); Parent root = (Parent) fxmlLoader.load(); Scene scene = new Scene(root, 1280, 720); String css = this.getClass().getResource("application.css").toExternalForm(); scene.getStylesheets().add(css); stage.setTitle("Hello!"); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(); } }
AppDrawerController.java
public class AppDrawerController implements Initializable { @FXML private Button refreshButton; @FXML private WebView webView; WebEngine webEngine; JSCallBack jsCallBack; // 生成WebView显示的HTML代码 public String loadApps(){ return "<div class=\"container\"><img src=\"file:/"+imagePath+"\"/><p class=\"title\">"+displayName+"</p><div class=\"overlay\"></div><div class=\"button-open\" onclick=\"app.processOnClickOpen(\'"+id+"\')\"><a href=\"#\"> Open </a></div><div class=\"button-option\" onclick=\"app.processOnClickOption(\'"+id+"\')\"><a href=\"#\"> Edit </a></div></div>"; } // 刷新页面方法 private void refreshPage(String html){ webEngine.loadContent(html); webEngine.reload(); } @SneakyThrows @Override public void initialize(URL url, ResourceBundle resourceBundle) { refreshButton.setOnAction(event -> { refreshPage(loadApps()); }); webEngine = webView.getEngine(); webEngine.getLoadWorker().stateProperty().addListener((obs, oldValue, newValue)-> { if (newValue == Worker.State.SUCCEEDED) { JSObject jsObject = (JSObject) webEngine.executeScript("window"); jsCallBack = new JSCallBack(webEngine); // 避免GC回收 jsObject.setMember("app", jsCallBack); } }); webEngine.setJavaScriptEnabled(true); var html = loadApps(); webEngine.loadContent(html); } // JS桥接类 public class JSCallBack { protected JSCallBack() {} // 打开应用,无需刷新 public void processOnClickOpen(String id) { log("Before open"); onAppOpen(id); log("After open"); } // 出现问题的方法:删除后无法刷新 public void processOnClickOption(String id) { // 删除应用逻辑正常执行 webEngine.loadContent(loadApps()+loadApps()); // 尝试刷新无效 webEngine.reload(); // 无效 } } }
问题核心代码段
public void processOnClickOption(String id) { // refreshPage(loadApps()+loadApps()) 同样无效 // refreshButton.fire() 手动点击按钮有效,但此方式无效 webEngine.loadContent(loadApps()+loadApps()); // 刷新失败 webEngine.reload(); // 无效 }
已尝试的无效方案
- 在JavaScript函数中添加
location.reload(),未生效; - 在
processOnClickOption()中调用refreshButton.fire(),手动点击按钮可刷新但此方式无效; - 在桥接类中重新设置WebEngine,无效;
- 排查线程问题,确认处于JavaFX Application线程,无异常。
解决方案
1. 移除多余的reload()调用
webEngine.loadContent()会直接加载新的HTML内容,紧接着调用reload()会重新加载之前的旧内容,直接覆盖新内容,这是无法刷新的核心原因。修改两处代码:
- 修复
refreshPage方法:private void refreshPage(String html){ webEngine.loadContent(html); // 移除webEngine.reload(); } - 修复
processOnClickOption方法:public void processOnClickOption(String id) { // 先执行删除操作,确保数据源已更新 deleteAppById(id); // 替换为你的实际删除逻辑 // 加载最新HTML,移除reload webEngine.loadContent(loadApps()); }
2. 确保loadApps()返回最新数据
检查删除快捷方式的逻辑,确认存储应用列表的数据源(集合、文件等)已经移除了对应项,这样loadApps()才能生成不包含已删除应用的新HTML。
3. 修复JSCallBack的WebEngine引用
当前JSCallBack构造方法未接收并保存WebEngine实例,虽然内部类可访问外部类的webEngine,但显式传入能避免潜在引用问题:
public class JSCallBack { private WebEngine webEngine; // 修改构造方法,接收并保存WebEngine public JSCallBack(WebEngine webEngine) { this.webEngine = webEngine; } public void processOnClickOption(String id) { deleteAppById(id); this.webEngine.loadContent(loadApps()); } }
4. 用Platform.runLater()确保线程安全
即使确认在JavaFX应用线程,包裹操作可避免潜在线程问题:
public void processOnClickOption(String id) { deleteAppById(id); Platform.runLater(() -> { webEngine.loadContent(loadApps()); }); }
内容的提问来源于stack exchange,提问作者Izzaz
相关产品推荐
相关产品推荐

