2

次の単純な MVP アーキテクチャを作成したいと思います。

  • vaadin のレイアウト、コンポーネント、スタイルに相当するクラスを表示します。機能しない。ビューは現在の ViewScope/SessionScope に関連付ける必要があるため@UIScopehttps://github.com/peholmst/vaadin4springを使用します

  • プレゼンターは、ビューを注入し、ビュー コンポーネントにリスナーを登録し、ユーザー入力を処理し、モデル サービスに委譲する必要があります。

問題:ビューをプレゼンターに挿入すると、ビューが再作成されるため、プレゼンターとビューが同じスコープにありません。したがって、バインディングは機能しません。上記の設計を実現するために何を変更できますか?

@VaadinComponent
@UIScope
public class LoginView {
    //form fields, buttons
}

@Controller
public class LoginPresenter implements ClickListener {
    @Autowired
    private LoginView view;

    @PostConstruct
    public void bind() {
        view.getLoginButton().addClickListener(this);
    }   

    @Override
    public void buttonClick(ClickEvent event) {
        //validate input and login
    }   
}
4

2 に答える 2

1

現在のプロジェクトで同様の問題があり、今のところ次の方法で解決しました。

@VaadinUI
public class MainUI extends UI {

    @Autowired
    private MainView mainView;

    @Autowired
    private MainPresenter mainPresenter;

    @Autowired
    private Test1Presenter test1Presenter;

    @Autowired
    private Test2Presenter test2Presenter;

    @Override
    protected void init(final VaadinRequest vaadinRequest) {

        setContent(this.mainView);
    }
}

@Component
@Scope("ui")
@VaadinView(name = "MainView")
public class MainView extends CustomComponent {

    private static final Logger LOGGER = LoggerFactory.getLogger(MainView.class);

    private TabSheet tabSheet;

    @Autowired
    private Test1Tab test1Tab;

    @Autowired
    private Test2Tab test2Tab;

    @PostConstruct
    private void init() {

        LOGGER.debug("MainView - Method init - Test1Tab: " + this.test1Tab);

        this.tabSheet = new TabSheet();
        this.tabSheet.addTab(this.test1Tab);
        this.tabSheet.addTab(this.test2Tab);

        setCompositionRoot(this.tabSheet);
    }

    public TabSheet getTabSheet() {

        return this.tabSheet;
    }

    public Test1Tab getTest1Tab() {

        return this.test1Tab;
    }

    public Test2Tab getTest2Tab() {

        return this.test2Tab;
    }
}

@Controller
@Scope("ui")
// Implementing Serializable was necessary to remove the warning "Storing
// non-serializable bean [...] with name [...] in UI space [...]".
public class MainPresenter implements Serializable {

    @Autowired
    private MainModel model;

    @Autowired
    private MainView view;

    @PostConstruct
    private void init() {

        // ...
    }
}

@Component
@Scope("ui")
@VaadinView(name = "Test1Tab")
public class AlarmsTab extends VerticalLayout {

    private final Button test1Button = new Button("Test 1");

    private final Button test2Button = new Button("Test 2");

    public Test1Tab() {

        setCaption("Test1");
        setMargin(true);
        setSpacing(true);

        addComponent(this.test1Button);
        addComponent(this.test2Button);
    }

    public Button getTest1Button() {

        return this.test1Button;
    }

    public Button getTest2Button() {

        return this.test2Button;
    }
}

@Controller
@Scope("ui")
public class Test1Presenter implements Serializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(Test1Presenter.class);

    @Autowired
    private MainModel model;

    @Autowired
    private Test1Tab view;

    @PostConstruct
    private void init() {

        LOGGER.debug("Test1Presenter - Method init - Test1Tab: " + this.view);

        this.view.getTest1Button().addClickListener(new ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {

               // ... 
            }
        });

        this.view.getTest2Button().addClickListener(new ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {

               // ... 
            }
        });
    }
}

このアプローチは機能しますが、スコープを正しく使用しているかどうかはよくわかりません (ビューとプレゼンターには @Scope("ui") の注釈が付けられています)。

これについて何かコメントはありますか?

于 2014-05-28T12:42:41.130 に答える