【发布时间】:2020-01-22 07:40:06
【问题描述】:
JavaFX 本身有一些 DI 方法来允许在 XML 描述的 UI 和控制器之间进行绑定:
<Pane fx:controller="foo.bar.MyController">
<children>
<Label fx:id="myLabel" furtherAttribute="..." />
</children>
</Pane>
Java 端如下所示:
public class MyController implements Initializable {
@FXML private Label myLabel;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// FXML-fields have been injected at this point of time:
myLabel.setText("Hello world!");
}
}
为此,我不能只创建 MyController 的实例。相反,我必须让 JavaFX 为我做一些事情:
FXMLLoader loader = new FXMLLoader(MyApp.class.getResource("/fxml/myFxmlFile.fxml"), rb);
loader.load();
MyController ctrl = (MyController) loader.getController();
到目前为止,一切顺利
但是,如果我想使用 Dagger 2 将一些非 FXML 依赖项注入此控制器类的构造函数,我会遇到问题,因为如果我使用 JavaFX,我无法控制实例化过程。
public class MyController implements Initializable {
@FXML private Label myLabel;
/*
How do I make this work?
private final SomeService myService;
@Inject
public MyController(SomeService myService) {
this.myService = myService;
}
*/
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// FXML-fields have been injected at this point of time:
myLabel.setText("Hello world!");
}
}
有一个 API 看起来很有前途:loader.setControllerFactory(...); 也许这是一个很好的起点。但我对这些库没有足够的经验,不知道如何解决这个问题。
【问题讨论】:
-
FXML 主要是一种 XML 模式,用于描述 JavaFX 的对象图,但它可以用于描述任何对象。您可以使用 FXML 来描述您的依赖项并由 FXML 加载程序注入吗?说实话,将服务混合到您的视图中听起来可能违反了关注点分离。这将是一个好地方,例如,使用可以注入服务引用的 Enterprise JavaBean,同时保留 MVC 设计提供的解耦。
-
您始终可以在代码中创建控制器,并在您的
FXMLLoader上调用setController,而不是使用fx:controller属性指定它。或者,您可以使用controllerFactory,它将fx:controller属性中指定的类映射到实际实例。 -
@James_D 是的,与此同时,我得出了同样的结论。调用 setController 是 唯一的方法,因为依赖项在编译时解决。基于反射的控制器工厂根本不可能。但是,不得在 .fxml 文件中指定控制器以避免冲突。如果没有人先发帖,我明天会自己回答这个问题(甚至可能在 github 上添加一个示例项目)。
-
我不知道 Dagger,所以我在这里可能错了,但
controllerFactory真的不必是基于反射的。 Here's a Spring example,如果你知道春天。
标签: java dependency-injection javafx dagger-2