首页 > 解决方案 > 加载 FXML 文件时,是否也加载了关联的控制器

问题描述

我为 ScreenController 类(由每个屏幕的各个控制器类扩展的类)创建了一个解决方案,它将处理我的应用程序中的基线屏幕层次结构。

在我的课程中,我使用一个函数将另一个 FXML 文件的内容添加(加载)到当前控制器的当前 AnchorPane 中。

我的问题是:

1)当新的 FXML 被加载时,FXML 使用的类(或者更确切地说,特定的控制器)是否也被实例化/加载?

2) 这样做时,如果新的 FXMl 的类被实例化/加载,之前的 FXML 的类是否从内存中释放?还是它仍在使用内存。

屏幕转换代码:

public void setScreen(String screen) throws Exception
{
    Parent root = FXMLLoader.load(getClass().getResource(screen));
    window.getChildren().setAll(root);
}

标签: javaintellij-ideajavafxfxml

解决方案


理解这FXMLLoader不是一个框架,尽管它可以用作框架的基础。没有容器可以管理控制器类的实例或加载的根。FXMLLoader由应用程序代码确定的对象会发生什么。

FXML 文件只是描述对象图的 XML 格式的文本文件。FXMLLoader简单地解释该文件并创建所述对象图1。当然,FXML 格式有一些特别添加的语法来处理 JavaFX 特定的功能(例如添加事件处理程序、绑定等)。


1)当新的 FXML 被加载时,FXML 使用的类(或者更确切地说,特定的控制器)是否也被实例化/加载?

如果您fx:controller在 FXML 文件的根元素中有一个属性,那么是的,会创建一个指定控制器类的新实例(默认情况下)。FXML 文件描述的所有对象也是如此。换句话说,每次加载 FXML 文件时,FXMLLoader都会返回根和控制器的新实例。控制器实例的创建方式可以通过controllerFactoryFXMLLoader.

如果您没有fx:controller属性,那么要么没有控制器实例,要么您需要以编程方式指定一个。在这种情况下,您需要手动提供控制器实例。

注意:永远不要在不同的 FXML 文件之间共享一个控制器类,也不要在不同的负载之间共享一个控制器实例。这样做会引起各种混乱,而且不必要地复杂。也就是说,拥有一个公共抽象类可能是合适的,只要它只具有每个子类共有的状态和行为。


2) 这样做时,如果新的 FXMl 的类被实例化/加载,之前的 FXML 的类是否从内存中释放?还是它仍在使用内存。

如本答案开头所述, anFXMLLoader只需解释 FXML 文件并创建适当的对象图1。一旦这样做,创建的对象会发生什么取决于您。只要对象可以被任何线程强烈访问,它们就不会被垃圾收集。

如果您问如果重用FXMLLoader实例会发生什么,我不完全确定,因为我从未尝试过。可以这么说,我建议FXMLLoader您每次要加载 FXML 文件(或使用静态load(URL)方法)时都创建一个新实例。


1.创建对象图后,如果存在控制器,则FXMLLoader还将注入任何适当的字段并“链接”所有适当的方法。


推荐阅读