首页 > 解决方案 > 任务不更新局部变量

问题描述

我正在使用任务读取文本文件,当用户单击“打开文件”菜单时调用该任务,它应该读取文本文件,然后更新局部变量“文本”,问题发生在第一次尝试,如果我打开一个文件,没有任何反应,并且文本字符串的值保持不变,如果我再次打开任何文件,一切都按预期工作,我找不到原因。

有任务的方法

private void readFile(File file){
    Task<String> task = new Task<String>() {
        @Override
        protected String call()  {
            List<String> list = EditorUtils.readFromFile(file);
            String str = list.stream().collect(Collectors.joining("\n"));
            return str;
        }
    };

    task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
        @Override
        public void handle(WorkerStateEvent t) {
            setCurrentText(task.getValue());
        }
    });
    task.setOnFailed(e -> setCurrentText("FAILED"));
    Thread t = new Thread(task);
    t.setDaemon(true);
    t.start();
}

设置当前文本

private void setCurrentText(String text){
    this.text = text;
}

控制器的方法

@FXML
void openMenuItemClick(ActionEvent event) {
    fileChooser.setTitle("title");
    fileChooser.getExtensionFilters().add
            (new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt"));
    File file = fileChooser.showOpenDialog(open.getParentPopup().getScene().getWindow());
    if (file != null){
        readFile(file);
        System.out.println(text); //prints null since "text" isn't initialized yet
    }
}

EditorUtils#readFromFile

public static List<String> readFromFile(File file){
    List<String> lines = new ArrayList<>();
    try {
        lines = Files.readAllLines(Paths.get(file.getPath()), StandardCharsets.UTF_8);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return lines;
}

标签: javafxconcurrency

解决方案


当使用多个线程时,这是完全正常的行为。您可以从后台线程上运行的任务访问该文件。完成后,此任务会触发 JavaFX 应用程序线程上的更新。

readFile返回时,任务可能尚未完成。Task用于Platform.runLater执行处理程序的事实onSucceeded导致在openMenuItemClick方法完成之前永远不会调用此处理程序,即使在System.out.println到达之前读取文件也是如此。

如果您需要根据 的结果更新 GUI Task,您应该从事件处理程序中执行此操作。更新text字段的代码在System.out.println(text);语句之后运行。第二次启动任务时,打印第一次单击菜单项时启动的任务的结果,而不是新的。println您可以通过将 移动到方法的开头来验证这一点openMenuItemClick


推荐阅读