簡體   English   中英

如何在 JavaFX 控制器中使用 Guice?

[英]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 文件。

不確定是否有任何缺點,但這種系統似乎對我有用:)

JavaFxGuice結合使用:

  1. 擴展 javafx.application.Application 並從 main 方法調用該類的啟動方法。 這是應用程序的入口點。
  2. 實例化您選擇的依賴注入容器。 例如 Google Guice 或 Weld。
  3. 在應用程序的 start 方法中,實例化 FXMLLoader 並設置它的控制器工廠以從容器中獲取控制器。 理想情況下,使用提供程序從容器本身獲取 FXMLLoader。 然后給它一個 .fxml 文件資源。 這將創建新創建窗口的內容。
  4. 將上一步中實例化的 Parent 對象提供給 Stage 對象(通常稱為 primaryStage)作為 start(Stage primaryStage) 方法的參數。
  5. 通過調用它的 show() 方法來顯示 primaryStage。

代碼示例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 PscheidlIntegrating JavaFX 8 with Guice 上為我們提供了這個智能代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM