有没有办法更快地编译/加载fxml文件一次,而不是每次重启应用程序?

n00*_*990 7 java javafx runtime javafx-2 javafx-8

我有一个程序,在执行时加载许多fxml文件.应用程序将在短时间内完成,加载应用程序只需要很长时间.

有许多fxml文件(20+),所有这些fxml文件都加载了Java代码.应用程序已完成并可以使用,但是每次执行程序时都会加载所有文件.fxml文件只能编译一次,因为完成后它们不会被更改吗?

java代码当然会被编译一次,它只是fxml文件.该应用程序现在需要25秒才能启动,加载fxml需要14秒.

有没有办法让这一切更快?

编辑#1:

是否有任何免费提供的工具可以更快地执行应用程序(Java)?或者执行时间仅取决于程序的编写方式?

哪种设计模式可以帮助缩短应用程序的执行时间?

编辑#2:

以下代码将简要解释我的问题:

package main;

.......
.......

public class MainClass {

    ....
    ....

    List<InformationController> controllerList;

    public mainClass(List<InformationControllers> controllerList) {
        this.controllerList = otherClass.getControllerList();
        loadFXMLFiles();
    }

    public void loadFXMLFiles() {
        for(InformationController controller : controllerList) {
            controller.loadFXML();
        }
        doOtherStuff();
    }

    ....

}
Run Code Online (Sandbox Code Playgroud)

所有那些InformationControllers也加载了其他fxml文件,所以它实际上是一个加载的fxml文件树.这是在应用程序的每个开始时加载的,所以有没有办法只加载一次这样做?

jew*_*sea 18

关于如何加速FXML性能

我将创建这个答案社区维基,如果有其他人有进一步的想法,请编辑并添加它们.

  1. 一个人不应该使用静态,FXMLLoader.load()而应该创建一个FXMLLoader实例,并使用实例loader.load()方法重用该实例.原因是FXML-Loader缓存,例如类查找,因此在加载下一个FXML文件时更快.
  2. 使用工具将FXML编译为Java,例如Tom Schindl的FXML编译器NetBeans FXML到Java转换器.
  3. 不要在任何给定时间加载任何超出您需要的FXML,例如,如果您现在不打算显示它,请不要加载它.
  4. 在后台线程中加载FXML(对于某些控件类型不起作用,例如Java 8中的Tooltip).
  5. 首先加载初始登录或启动屏幕,然后在显示启动或登录屏幕时加载其余的FXML.在登录屏幕接受凭据后,我在某些应用程序中加载FXML.
  6. 通过删除不必要的节点来降低应用程序UI的复杂性.
  7. 确保您没有在控制器的initialize方法中对JavaFX UI线程执行不必要的工作(例如,读取数据库).
  8. FXMLLoader.load()JavaFX 8中的文档包含对FXML模板的引用,但我不认为它曾经实现过,所以它可能对你没有帮助.
  9. 我听说提到FXML的静态方法很慢.
  10. 使用JavaFX最新开发版本.
  11. 从FXML加载节点层次结构后,重新使用层次结构,而不是将其丢弃并加载新层次结构(例如,如果您有一个使用FXML构建内容的对话窗口,当用户关闭对话框时,只需隐藏它,何时隐藏它你需要再次显示一个类似的对话框,只显示隐藏的对话框而不是构建一个全新的对话框和场景图.

反思是FXML缓慢的原因

我认为Java 8 FXML实现缓慢的关键原因是它如此依赖于反射和反射很慢,如反射教程中所述:

由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化.因此,反射操作的性能低于非反射操作,并且应避免在性能敏感应用程序中频繁调用的代码段中.

  • 您忘记并可能添加的一个重点是,不应该使用静态FXMLLoader.load(),而是创建FXMLLoader的实例并重用该实例.原因是FXML-Loader缓存例如类查找,因此加载下一个FXML文件的速度更快 (2认同)
  • 这不起作用.您不能重复使用相同的FXMLLoader实例来重新加载不同的甚至是同一个文档.您将获得所有类型的错误,例如重复的fx:ids,root已经设置,等等.它并不意味着以这种方式使用. (2认同)
  • 是的,FXMLLoader 不适合重用。但是您可以在加载之前通过“setRoot(null)”和“setController(null)”来实现。然而,由于使用缓存而更快的说法仍然是“错误的”,因为缓存在每次加载操作之前都会被逐出(请参阅“clearImports()”) (2认同)
  • 出于好奇(想看看是否可以保留单个控制器引用),我尝试了它,似乎可以重用 FXML 加载程序。Loader、Parent 和 Scene 可以声明为类字段(例如 myLoader 等)。然后,在空检查中,在第一次运行时进行一次性初始化。然后每次都可以在新舞台上使用这些实例。说不出有什么好处。 (2认同)