我有一个JavaFX应用程序,我想介绍Guice,因为我的代码 现在充满了因子,只是为了测试。
我有一个用例,其中我有一个特定视图的控制器类。 这个控制器类有一个viewmodel,我将模型传递给viewmodel via 控制器类的构造函数。
在控制器类中,我有一个提供编辑/保存/删除操作的contactservice对象。 截至目前,我有一个该对象的接口,并提供一个实现和一个模拟。可以通过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和类似的框架,但我如何将这两者结合起来呢? 特别是如何让这些字段注入并自己实现控制器或者至少给它一些构造函数args?
答案 0 :(得分:13)
我不使用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();
答案 1 :(得分:2)
对于称为afterburner.fx的javaFX,有一个很好的DI框架。看看它,我认为这是你正在寻找的工具。
答案 2 :(得分:0)
假设您(可以)手动/ guice而不是FXML实例化控制器,如果需要将任何非DIable参数传递给构造函数,则可以使用https://github.com/google/guice/wiki/AssistedInject。然后,您可以使用.setController(this)手动将控制器设置为FXMLLoader,并将FXML文件加载到控制器的构造函数中。
不确定是否有任何缺点,但这种系统似乎对我有用:)
答案 3 :(得分:0)
要与 Guice 一起使用 JavaFx :
代码示例 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
处向我们提供了此智能代码