[英]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.