[英]How can i use Guice in JavaFX controllers?
我有一个 JavaFX 应用程序,我想在其中引入 Guice,因为我的代码现在充满了工厂,仅用于测试目的。
我有一个用例,我有一个特定视图的控制器类。 这个控制器类有一个视图模型,我通过控制器类的构造函数将模型传递给视图模型。
在控制器类中,我有一个 contactservice 对象,它提供编辑/保存/删除操作。 到目前为止,我有一个该对象的接口,并提供了一个实现和一个 Mock。 可以通过 Factory.getInstance() 方法检索此对象。
我想做的是这样的:
public class NewContactController implements Initializable {
// ------------------------------------------------------------------------
// to inject by guice
// ------------------------------------------------------------------------
private ContactService contactService;
@Inject
public void setContactService(ContactService srv) {
this.contactService = srv;
}
// edit window
public NewContactController(Contact c) {
this.viewModel = new NewContactViewModel(c);
}
// new window
public NewContactController() {
this.viewModel = new NewContactViewModel();
}
@FXML
void onSave(ActionEvent event) {
//do work like edit a contcat,
contactService.editContact(viewModel.getModelToSave());
}
@Override
public void initialize(URL location, ResourceBundle resources) {
// bind to viewmodel---------------------------------------------------
}
}
我怎样才能做到这一点? 做这样的事情是个好主意吗? 当我在寻找解决方案时,我发现了fx-guice和类似的框架,但我如何将这两者结合起来? 特别是我怎样才能让这个字段被注入并自己实例化控制器,或者至少给它一些构造函数参数?
我不使用 Guice,但最简单的方法似乎只是在FXMLLoader
上使用控制器工厂。 您可以创建一个控制器工厂,指示FXMLLoader
使用 Guice 来初始化您的控制器:
final Injector injector = Guice.createInjector(...);
FXMLLoader loader = new FXMLLoader(getClass().getResource(...));
loader.setControllerFactory(new Callback<Class<?>, Object>() {
@Override
public Object call(Class<?> type) {
return injector.getInstance(type);
}
});
// In Java 8, replace the above with
// loader.setControllerFactory(injector::getInstance);
Parent root = loader.<Parent>load();
javaFX 有一个很好的 DI 框架,称为afterburner.fx 。 检查一下,我认为这是您正在寻找的工具。
假设您(可以)手动/guice 而不是从 FXML 实例化控制器,如果您需要将任何非 DIable 参数传递给构造函数,则可以使用https://github.com/google/guice/wiki/AssistedInject 。 然后,您可以使用 .setController(this) 将控制器手动设置为 FXMLLoader,并在控制器的构造函数中加载 FXML 文件。
不确定是否有任何缺点,但这种系统似乎对我有用:)
将JavaFx与Guice结合使用:
代码示例MyApp.java
public class MyApp extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Injector injector = Guice.createInjector(new GuiceModule());
//The FXMLLoader is instantiated the way Google Guice offers - the FXMLLoader instance
// is built in a separated Provider<FXMLLoader> called FXMLLoaderProvider.
FXMLLoader fxmlLoader = injector.getInstance(FXMLLoader.class);
try (InputStream fxmlInputStream = ClassLoader.getSystemResourceAsStream("fxml\\login.fxml")) {
Parent parent = fxmlLoader.load(fxmlInputStream);
primaryStage.setScene(new Scene(parent));
primaryStage.setTitle("Access mini Stock App v1.1");
primaryStage.show();
primaryStage.setOnCloseRequest(e -> {
System.exit(0);
});
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
launch();
}
}
然后 FXMLLoaderProvider.java
public class FXMLLoaderProvider implements Provider<FXMLLoader> {
@Inject Injector injector;
@Override
public FXMLLoader get() {
FXMLLoader loader = new FXMLLoader();
loader.setControllerFactory(p -> {
return injector.getInstance(p);
});
return loader;
}
}
感谢先生。 Pavel Pscheidl在Integrating JavaFX 8 with Guice 上为我们提供了这个智能代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.