You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:55:16