如何使用 Vaadin CDI 和 Navigator 实现 MVP?
How to implement MVP using Vaadin CDI and Navigator?
我想在我的 Web 应用程序中使用 Vaadin 实现 MVP 模式。我正在使用 Vaadin Navigator 和 CDIViewProvider,类似这样:
//MyUI.java
public class MyUI extends UI {
@Inject
CDIViewProvider viewProvider;
Navigator navigator;
@Override
protected void init(VaadinRequest vaadinRequest) {
//UI setup
navigator = new Navigator(this, someContainer);
navigator.addProvider(viewProvider);
getNavigator().navigateTo("myView");
}
}
//MyViewImpl.java
@CDIView("myView")
public class MyViewImpl extends VerticalLayout implements com.vaadin.navigator.View, MyView {
// ...
据我了解,视图提供程序实例化了一个 MyViewImpl 的对象,该对象是 ViewScoped,即当用户浏览此视图的 to/out 时,它会得到 created/destroyed。接下来需要考虑在哪里实例化这个view的presenter。我想过让它成为 SessionScoped 并将其注入到视图中:
// ... continue MyViewImpl.java
@Inject
private MyViewListener presenter;
// in some of the MyViewImpl methods we can do stuff like presenter.buttonClicked();
}
//MyViewPresenter.java
@SessionScoped
public class MyViewPresenter implements MyView.MyViewListener {
MyView view; //how can the presenter obtain the view here ?
@PostConstruct
public void init()
@Override
public void buttonClicked() {
view.displaySomething();
}
}
//MyView.java
public interface MyView {
public interface MyViewListener {
public void buttonClicked();
}
public void displaySomething();
}
正如我在演示者引用视图后面的评论中指出的那样,我不知道演示者如何获得视图实例(由视图提供者创建)。让演示者成为 SessionScoped 是否有意义,而视图在视图更改时获得 created/destroyed?另一种方法是视图没有对演示者的引用,但是演示者将自己添加为视图的侦听器。但是在这种情况下,我再次不知道在哪里实例化演示者以及如何获取对当前视图的引用。
我认为重点是视图让演示者注入,反之亦然。因此,您采用上述方法的一种策略是使 Presenter
@Dependent
范围内并在视图中放置 @Inject
MyViewPresenter
presenter
和 @Inject
MyView
view
进入演示者。 @Dependent
使它们驻留在同一范围内,这很可能是您想要实现的目标
不要尝试注入视图,而是在演示者中使用视图 setter 并从视图的 @PostConstruct
:
中调用它
@Dependent
class MyPresenter {
private MyView view;
public void setView(MyView view) {
this.view = view;
}
}
public interface MyView {
}
@CDIView("my-view")
public class MyViewImpl extends VerticalLayout implements View, MyView {
@Inject
private MyPresenter presenter;
@PostConstruct
private void init() {
presenter.setView(this);
}
}
我认为创建顺序是这里令人困惑的问题。在某种程度上,视图具有更高的优先级,因为它们是在您调用 getNavigator().navigateTo("my-view")
时由 Vaadin 创建的。 Presenter 由 CDI 的视图实例化(即使它监督视图)并且应该具有 @Dependent
范围。
我想在我的 Web 应用程序中使用 Vaadin 实现 MVP 模式。我正在使用 Vaadin Navigator 和 CDIViewProvider,类似这样:
//MyUI.java
public class MyUI extends UI {
@Inject
CDIViewProvider viewProvider;
Navigator navigator;
@Override
protected void init(VaadinRequest vaadinRequest) {
//UI setup
navigator = new Navigator(this, someContainer);
navigator.addProvider(viewProvider);
getNavigator().navigateTo("myView");
}
}
//MyViewImpl.java
@CDIView("myView")
public class MyViewImpl extends VerticalLayout implements com.vaadin.navigator.View, MyView {
// ...
据我了解,视图提供程序实例化了一个 MyViewImpl 的对象,该对象是 ViewScoped,即当用户浏览此视图的 to/out 时,它会得到 created/destroyed。接下来需要考虑在哪里实例化这个view的presenter。我想过让它成为 SessionScoped 并将其注入到视图中:
// ... continue MyViewImpl.java
@Inject
private MyViewListener presenter;
// in some of the MyViewImpl methods we can do stuff like presenter.buttonClicked();
}
//MyViewPresenter.java
@SessionScoped
public class MyViewPresenter implements MyView.MyViewListener {
MyView view; //how can the presenter obtain the view here ?
@PostConstruct
public void init()
@Override
public void buttonClicked() {
view.displaySomething();
}
}
//MyView.java
public interface MyView {
public interface MyViewListener {
public void buttonClicked();
}
public void displaySomething();
}
正如我在演示者引用视图后面的评论中指出的那样,我不知道演示者如何获得视图实例(由视图提供者创建)。让演示者成为 SessionScoped 是否有意义,而视图在视图更改时获得 created/destroyed?另一种方法是视图没有对演示者的引用,但是演示者将自己添加为视图的侦听器。但是在这种情况下,我再次不知道在哪里实例化演示者以及如何获取对当前视图的引用。
我认为重点是视图让演示者注入,反之亦然。因此,您采用上述方法的一种策略是使 Presenter
@Dependent
范围内并在视图中放置 @Inject
MyViewPresenter
presenter
和 @Inject
MyView
view
进入演示者。 @Dependent
使它们驻留在同一范围内,这很可能是您想要实现的目标
不要尝试注入视图,而是在演示者中使用视图 setter 并从视图的 @PostConstruct
:
@Dependent
class MyPresenter {
private MyView view;
public void setView(MyView view) {
this.view = view;
}
}
public interface MyView {
}
@CDIView("my-view")
public class MyViewImpl extends VerticalLayout implements View, MyView {
@Inject
private MyPresenter presenter;
@PostConstruct
private void init() {
presenter.setView(this);
}
}
我认为创建顺序是这里令人困惑的问题。在某种程度上,视图具有更高的优先级,因为它们是在您调用 getNavigator().navigateTo("my-view")
时由 Vaadin 创建的。 Presenter 由 CDI 的视图实例化(即使它监督视图)并且应该具有 @Dependent
范围。