如何使用Vaadin CDI和Navigator实施MVP? [英] How to implement MVP using Vaadin CDI and Navigator?
问题描述
我想使用Vaadin在我的Web应用程序中实现MVP模式.我正在使用Vaadin导航器和CDIViewProvider,如下所示:
I would like to implement the MVP pattern in my web application using Vaadin. I am using the Vaadin Navigator and the CDIViewProvider, something like so:
//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),即,当用户导航到该视图/从该视图中移出时,该对象被创建/销毁.接下来,我需要考虑在哪里实例化此视图的演示者.我考虑过将其设为SessionScoped并将其注入视图:
To my understanding the view provider instantiates an object of MyViewImpl which is ViewScoped, i.e. it gets created/destroyed as the user navigates to/out of this view. Next I need to think about where to instantiate the presenter of this view. I thought about making it SessionScoped and inject it to the view:
// ... 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();
}
正如我已经在演示者引用该视图后面的注释中指出的那样,我不知道演示者如何获得该视图实例的持有权(该实例由视图提供者创建).当视图改变时,只要创建/销毁视图,让演示者使用SessionScope甚至有意义吗?一种替代方式是该视图没有对演示者的引用,但是演示者将自己添加为该视图的侦听器.但是,在这种情况下,我再次不知道在哪里实例化演示者以及如何获取对当前视图的引用.
As I already pointed out in the comment behind the presenters reference to the view I do not know how the presenter can get a hold of the view instance (which is created by the view provider). Does it even make sense to have the presenter be SessionScoped, while the views get created/destroyed whenever the view changes ? An alternative way would be that the view does not have a reference to the presenter, but that the presenter adds itself as the listener to the view. However in this case I again do not know where to instantiate the presenter and how to get a reference to the current view.
推荐答案
不要尝试注入视图,而是在演示者中使用视图设置器,并从视图的@PostConstruct
中调用它:
Don't try to inject the view, use a view setter in presenter instead and call it from view's @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
范围.
I think that creation order is the confusing issue here. In a way views have higher priority as they are created by Vaadin when you call getNavigator().navigateTo("my-view")
. Presenter is instantiated by the view by CDI (even though it supervises the view) and should have @Dependent
scope.
这篇关于如何使用Vaadin CDI和Navigator实施MVP?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!