java - 使用 Guice 将数据注入(inject) JavaFX ViewController

标签 java javafx guice

今天我将 Guice 添加到我的 Java FX 应用程序中。主要目标是用注入(inject)替换我的单例并打破依赖关系。 到目前为止,一切正常,这是我必须启动新场景的代码:

public class App extends Application{

public static void main(String[] args){
    launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
    final String LANGUAGE_BUNDLE = "myBundlePath";
    final String FXML = "myFXMLPath";

    try {
        ResourceBundle resourceBundle = ResourceBundle.getBundle(LANGUAGE_BUNDLE, Locale.GERMAN, this.getClass().getClassLoader());
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(FXML), resourceBundle, new JavaFXBuilderFactory(), getGuiceControllerFactory());
        primaryStage.setScene(new Scene(fxmlLoader.load()));
        primaryStage.show();
    }catch (IOException ex) {
        ex.printStackTrace();
    }
}

private Callback<Class<?>, Object> getGuiceControllerFactory(){
    Injector injector = Guice.createInjector(new GuiceModule());
    return new Callback<Class<?>, Object>() {
        @Override
        public Object call(Class<?> clazz) {
            return injector.getInstance(clazz);
        }
    };
}
}

我的 Guice 模块如下所示:

public class GuiceModule extends AbstractModule {
@Override
protected void configure() {
    bind(ITester.class).to(Tester.class);
    bind(ISecondTest.class).to(SecondTest.class);
}
}

请注意,我替换了资源包和 fxml 文件的路径,因为它们会泄露我的身份。但是加载并且一切正常,所以这应该不是问题;)

现在的问题是,我想通过在不同 View 中单击按钮来实例化一个新 View 。第二个 View 应显示 View 1 中数据的更详细版本。 我需要传递给第二个 View 的所有内容都是整数(或 int),但我完全不知道如何做到这一点。

我有标准的 FX 设置:

View.fxml (with a reference to the ViewController)
ViewController.java
Model.java
ViewModel.java

然后,ViewController 绑定(bind)到 ViewModel 提供的属性。 我需要 int 来选择正确的模型。

我能找到的所有内容都是关于注释@Named,但据我所知,这无法用于注入(inject)动态数据。

你能给我一个提示,我想做的事情叫什么吗? 或者长话短说:如何在第二个 ViewController 中注入(inject)由不同 View 选择的变量,并将其余部分保留在标准 FX 方式中?

感谢任何帮助,并提前致谢!

问候,克里斯蒂安

最佳答案

经过一番尝试,我似乎自己找到了解决方案! 然而,我正在做的事情“感觉”很丑,所以我想得到一些确认;)

首先是理论:Guice 支持“AssistedInject”。这是当类不能由默认构造函数构造时。为了能够使用 AssistedInject,您必须下载扩展(我从 maven repository 下载了 jar)。

AssistedInject 为您所做的是,它允许您指定一个为您构建变量的工厂。这就是我所做的:

首先,为稍后要使用的类创建一个接口(interface),在我的例子中:

public interface IViewController {
}

其次,为工厂创建一个接口(interface)。重要提示:您不必实现工厂

public interface IControllerFactory {

    ViewController create(@Assisted int myInt);

}

第三,将带有相应参数的构造函数添加到您稍后要实例化的类中,并让它实现您创建的接口(interface),如下所示:

public class ViewController implements IViewController{

@AssistedInject
public ViewController(@Assisted int i){
    final String LANGUAGE_BUNDLE = "languageBundle";
    final String FXML = "View.fxml";

    try{
        ResourceBundle resourceBundle = ResourceBundle.getBundle(LANGUAGE_BUNDLE, Locale.GERMAN, this.getClass().getClassLoader());
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(FXML), resourceBundle, new JavaFXBuilderFactory());
        fxmlLoader.setController(this);
        Stage second = new Stage();
        second.setScene(new Scene(fxmlLoader.load()));
        second.show();
    }catch (IOException e){
        e.printStackTrace();
    }
    System.out.println("ViewController constructor called with: " + i);
}

以下几点需要注意:

  • 方法的注释“@AssistedInject”
  • 我们要从外部提供的参数的注释“@Assisted”
  • 我们手动设置加载器的 Controller (使用 fxmlLoader.setController(this);)
  • 我必须删除 fxml 文件中的 Controller 配置,因此 fxml 中没有“fx:controller”!

接下来,我们需要将一个变量添加到要实例化另一个类的类中:

@Inject
IControllerFactory controllerFactory;

我们可以在类中使用它,如下所示:

controllerFactory.create(3)

注意:我们将方法称为“create”,但我们从未在 ViewController 类中实现过该方法! Guice 知道它必须调用构造函数 - magic

最后一步,我们需要在 GuiceModule 中添加与上下文的连接,如下所示:

@Override
protected void configure(){
    install(new FactoryModuleBuilder()
            .implement(IPagingDirectoryViewController.class, PagingDirectoryViewController.class)
            .build(IPagingDirectoryControllerFactory.class));
}

注意我收到错误:无法解析方法'implement java.lang.Class<"The interface class">, java.lang.Class<"The Implementing class">'。这是因为我忘记让我的 Controller 类实现该接口(interface)。

好的,这就是我的工作原理。 然而,正如我所说,我会很高兴听到一些意见!

问候,克里斯蒂安

关于java - 使用 Guice 将数据注入(inject) JavaFX ViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36165151/

相关文章:

guice - 使用 Google Guice 在运行时注入(inject)依赖项

java - 使用Guice,如何提供同一类型的不同实例?

java - 如何使用 "/"拆分 arraylist<File>

java - java中的参照物是什么?

java - 检查是否有一个数组的大小为 k 的子集具有 n 的和倍数

java - 需要使用 MapBinder 进行显式绑定(bind) - Guice 4.0 beta4

java - 如何创建跨服务域模型映射?

JavaFX 可以在二维形状中写入 "Borderless"吗?

java - 按钮的 css 样式不起作用

javafx.fxml.LoadException : Invalid property