如何使用异步回调实现MVC?

时间:2015-08-03 19:00:02

标签: java gwt model-view-controller

我目前正在重构我的GWT客户端并尝试将MVC模式应用于所有相关类。我的问题是我不确定这里有两件事:

  • 我在哪里控制哪个视图显示?例如,如果用户登录并且应该加载起始页面。控制器会加载该页面还是模型?
  • 我如何最好地处理异步回调以及谁(模型或控制器)应该持有异步服务?

我有这个简单的登录示例,它是我目前的实际代码:

LoginModel

// LoginModel appears kind of obsolete ..
public class LoginModel {

    private final LoginServiceAsync loginService = LoginService.Util.getInstance();

    public void onLoginClick(String userId, String password, AsyncCallback<UserDTO> asyncCallback) {        
        // Login on the server ..
        this.loginService.login(userId, password, asyncCallback);   
    }
}

LoginView

public class LoginView extends Composite {

    private static UILoginUiBinder uiBinder = GWT.create(UILoginUiBinder.class);

    @UiField Button btnLogin;
    @UiField TextBox txtPassword;
    @UiField TextBox txtUserID;

    interface UILoginUiBinder extends UiBinder<Widget, LoginView> {
    }

    public LoginView() {
        initWidget(uiBinder.createAndBindUi(this));
    }

    public void addLoginButtonClickHandler(ClickHandler clickHandler) {
        this.btnLogin.addClickHandler(clickHandler);
    }

    public String getUserId() {
        return this.txtUserID.getText();
    }

    public String getPassword() {
        return this.txtPassword.getText();
    }

    public void displayLoginFailure() {     
        // TODO display login failure ..
    }
}

的LoginController

public class LoginController {

    private final LoginModel loginModel;

    private final LoginView loginView;

    public LoginController(LoginModel loginModel, final LoginView loginView) {

        this.loginModel = loginModel;
        this.loginView = loginView;
        this.loginView.addLoginButtonClickHandler(new LoginButtonClickHandler());
    }

    private class LoginButtonClickHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {

            loginModel.onLoginClick(loginView.getUserId(), loginView.getPassword(), new AsyncCallback<UserDTO>() {
                public void onFailure(Throwable caught) {
                    onLoginFailure(caught);
                }

                public void onSuccess(UserDTO userDto) {
                    onLoginSuccess(userDto);
                }
            });
        }
    }

    public void onLoginFailure(Throwable caught) {
        Throwable cause = caught.getCause();    
        if (cause instanceof LoginException) {
            GWT.log("Cause: " + cause.getMessage());
            cause.printStackTrace();
        }

        this.loginView.displayLoginFailure();
    }

    public void onLoginSuccess(UserDTO userDto) {
        // NOTE: UIStart is what is going to become StartView!
        UIStart home = new UIStart();
        RootPanel.get("mainUIContainer").clear();
        RootPanel.get("mainUIContainer").add(home);
    }
}

这是MVC模式的一个很好的实现吗?我可以做得更好吗?

2 个答案:

答案 0 :(得分:1)

模型 - 视图 - 控制器(MVC)是用于实现用户界面的软件架构模式。它将给定的软件应用程序划分为三个相互关联的部分,以便将信息的内部表示与向用户呈现或接受信息的方式分开(来源:Wikipedia

说,MVC有3个组件,

1)模型:理想情况下,它应该只包含getter和setter。这里不应该提到商业逻辑

2)查看:此部分仅包含视图。您不会在此处将视图链接到主html。它只是一个简单的视图,可以访问模型。

3)控制器:你所有的商业逻辑都应该放在这里。控制器可以访问视图和模型。

MVC w.r.t GWT应该是这样的。

第一个控制器被实例化。然后,控制器创建模型和视图的实例。

模型与视图链接,通常模型作为参数传递给视图。您可以像使用命令模式中的角度一样实现双重绑定,并根据需要更改侦听器或更新模型值(通常在保存或提交时)

现在来到你的异步部分。所有异步处理都应该在控制器上完成。在控制器中,异步调用成功后,应该更新模型,并且当模型与视图链接时,模型将更新视图。

我希望这可以回答你的问题并解释你的MVC范例。

答案 1 :(得分:1)

Ray Ryan在Google I / O 2009上发表了一篇演讲:Best Practices for Architecting GWT App

在GWT中你不使用MVC,你使用MVP(模型 - 视图 - 演示者),它更清晰地划分部分。您可以将MVP用于您的小部件和屏幕。 接下来使用EventBus来解耦组件。

最后你应该使用Acticities&amp;在您的应用程序内导航的地方。

看看这里: MVP Activities and Places。 这是一个很好的起源。

此外,您可以查看GWT-Platform GWTPmvp4g,因为它们是GWT中mvp模式的不同实现。

正如Abhijith Nagaraja已经提到的那样:在演示者中进行异步调用。

修改:另请参阅Demystifying MVP and EventBus in GWT(摘自评论部分)。