我可能会错过一些解决方法,但我还想找到一个解决方案,我可以将依赖关系,例如我的事件总线实例和一些服务接口传递给我的javafx应用程序。
我有一个UI-Init类,它只是启动应用程序并接收UI的一些依赖项,如eventBus:
public class Frontend {
public Frontend(MBassador<EventBase> eventBus) {
Application.launch(AppGui.class);
}
我的AppGui类扩展了Application并加载了FXML:
public class AppGui extends Application {
private Stage primaryStage;
private GridPane rootLayout;
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("RootLayout.fxml"));
rootLayout = (GridPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
scene.setFill(null);
primaryStage.setScene(scene);
RootLayoutController rootController = loader.getController();
rootController.init(/*here I would like to inject my eventBus*/);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
现在,我如何将eventBus和其他服务接口传递给此控制器?我已经读过使用像guice(How can JavaFX controllers access other services?)或者afterburner.fx这样的DI框架来使用它。但即使我在我的应用程序的其余部分使用guice,我还需要将Injector实例传递给JavaFX应用程序?。
但是Application.launch(AppGui.class);是静态的,并在javafx线程上内部创建一个AppGui实例,我无法访问该实例。那么如何在不使用静态变量的情况下将依赖项注入AppGui对象呢?
答案 0 :(得分:2)
以下是我的工作:
Application
类有几个生命周期回调,init()
和stop()
。
来自Javadocs:
public void init() throws java.lang.Exception
应用程序初始化方法。在加载和构造Application类之后立即调用此方法。应用程序可以覆盖此方法以在实际启动应用程序之前执行初始化。
public void stop() throws java.lang.Exception
当应用程序停止时调用此方法,并为准备应用程序退出和销毁资源提供方便的位置。
同样来自Javadocs,生命周期:
- 构造指定的
的实例Application
类- 调用
init()
方法- 调用
start(javafx.stage.Stage)
方法- 等待应用程序完成,当发生以下任一情况时会发生:
- 应用程序调用{{1}}
- 最后一个窗口已关闭且
Platform.exit()
上的implicitExit
属性为Platform
- 调用stop()方法
醇>
我在true
中启动IoC容器并在init()
中将其停止。现在,我的stop()
类具有对IoC容器的引用,并且可以为第一个控制器提供其依赖项。
事实上,我让IoC框架管理控制器。我使用Application
将它们设置为加载的FXML,而不是使用FXMLLoader.setController()
指定它们。
答案 1 :(得分:0)
在调用launch()
之前,您可以将静态引用传递给应用程序类。类似的东西:
public class Frontend {
public Frontend(MBassador<EventBase> eventBus) {
AppGui.setEventBus(eventBus);
Application.launch(AppGui.class);
}
}
public class AppGui extends Application {
private static MBassador<EventBase> eventBus;
public static void setEventBus(MBassador<EventBase> eventBus) {
this.eventBus = eventBus;
}
private MBassador<EventBase> eventBus;
@Override
public void init() {
if (AppGui.eventBus == null) {
throw new IllegalStateException();
// or however you want to handle that state
} else {
this.eventBus = AppGui.eventBus;
AppGui.eventBus = null;
}
}
}
您是否保留并使用静态引用,或者将静态引用复制到本地引用取决于您和应用程序的设计。如果您希望实例化多个AppGui副本,则可能需要本地引用。
不知道这是否是线程安全的(可能不是)。来自@Nikos和@James_D的建议是坚实的,首选......但有时你只需要一个黑客。 :) YMMV