浅谈Android中MVC、MVP、MVVM模式(二)

二、MVP模式在Android中的发展
    首先,我们接着上篇 《浅谈Android中MVC、MVP、MVVM模式(一)》,在上一篇中,我们已经熟悉了MVC模式, 也提出了MVC模式的一些弊端,正是因为MVC在我们Android项目开发中存在的一些弊端, 从而由MVC眼花出了一种新的模式——MVP。
    MVP全名是Model View Presenter,是由MVC演变过来一种新型架构框架。
    对于MVP, 很多人也都能说出一二来, 它是MCV的一种演变、升级,让Model和View完全解耦。
    那么,MVP与MVC究竟存在着那些差别呢? 为什么能被广大的Android程序员所接受呢?
  • View: 对应于Activity,负责View的绘制以及用户的交互
  • Modle: 依然是业务逻辑和实体模型
  • Presenter: 负责完成Modle与View之间的交互

当MVC架构改为MVP以后,Presenter的出现,Activity就只负责与界面相关的View的展示,Presenter负责完成View层与Modle层的交互,这样减少了Activity的职责,将复杂的逻辑代码提取到了Presenter中进行处理,极大地降低了模块间的耦合度。

其实,我个人认为MVP的核心思想就是面向接口编程。

其他的概念性的东西不多说了,有兴趣的可以自行百度下, 下面还是用一个简单的登录的demo来演示下MVP模式、

demo的效果图和前面MVC的一样, 先来看下MVP的项目结构,

OK, 接下来一步一步的编写思路。

(一)Model
和前面的MVC一样, 首先实体User,还有就是业务方法login(), 这里我对之前的MVC的简单demo更细化的分离了一下, 更确切的符合面向接口编程。下面看具体代码。
User.java就不贴了, 跟前面MVC一样。就贴下业务这块的
//Modle 业务抽象接口
public interface IUserHttp {
    void login(String username, String password, OnResultListener<User> listener);
}
//Model 业务回调接口
public interface OnResultListener<T> {
    /** 请求异常 */
    int STATE_ERROR = -1;
    /** 请求成功 */
    int STATE_SUCCEED = 0x11;
    /** 请求成功, 无数据 */
    int STATE_SUCCEED_EMPTY = 0x22;
    /** 请求成功, JSON异常 */
    int STATE_SUCCEED_JSON_ERROR = 0x33;
    /** 未请求 */
    int STATE_UNGEBETEN = 0x44;

    /**
     * 请求结果返回
     * @param state 状态码
     * @param data List集合返回
     * @param result json字符串返回
     * @return 是否自行处理结果
     */
    boolean onResult(int state, List<T> data, T result);
}
//Modle 业务实现
public class UserHttpImp implements IUserHttp {

    private Handler mHandler = new Handler(); //Demo, 在此简单处理

    @Override
    public void login(final String username, final String password, final OnResultListener<User> listener) {
        //模拟子线程耗时操作
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //模拟登录成功
                if ("123".equals(username) && "123".equals(password)) {
                    final User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            listener.onResult(OnResultListener.STATE_SUCCEED, null, user);
                        }
                    });
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            listener.onResult(OnResultListener.STATE_ERROR, null, null);
                        }
                    });
                }
            }
        }.start();
    }
}

(二)View
    上面我们说到,MVP的核心思想就是面向接口编程, 也就是说Presenter与View的交互是通过接口来实现的,所以, 这里我们要定义一个接口IUserLoginView,这个View的接口中应当有哪些方法呢? 这就是需要我们根据需求去分析了。
    首先,login,需要有用户名、密码,那么对应有
  • String getUserName();
  • String getPassword();
    再看, 我们请求网络肯定时耗时操作, 为了用户体验,肯定是会有个加载的提示进度框
  • void showLoading();
  • void hideLoading();
    最后就是成功与失败的结果显示
  • void toMainActivity(User user);
  • void showFailedError();
综上,接口如下:
//View 面向接口
public interface IUserLoginView {
    String getUserName();

    String getPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity(User user);

    void showFailedError();
}
View的接口写好了,接下来就是接口的实现类了, 那么它的实现类是谁呢? 哈哈,其实就是我们的Activity了, MVP中的View其实就是Activity。
//View Activity就只负责与界面相关的View的展示
public class MvpLoginActivity extends AppCompatActivity implements View.OnClickListener, IUserLoginView {

    private ProgressDialog mPdLoading;
    private EditText et_username;
    private EditText et_password;
    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this, new UserHttpImp());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvclogin);

        et_username = (EditText) findViewById(R.id.et_username);
        et_password = (EditText) findViewById(R.id.et_password);
        mPdLoading = new ProgressDialog(this);

        findViewById(R.id.bt_login).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_login:
                login();
                break;
        }
    }

    //登录
    private void login() {
        mUserLoginPresenter.login();
    }

    @Override
    public String getUserName() {
        return et_username.getText().toString();
    }

    @Override
    public String getPassword() {
        return et_password.getText().toString();
    }

    @Override
    public void showLoading() {
        mPdLoading.show();
    }

    @Override
    public void hideLoading() {
        mPdLoading.dismiss();
    }

    @Override
    public void toMainActivity(User user) {
        Toast.makeText(this, user.getUsername() +
                " login success , to MainActivity", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError() {
        Toast.makeText(this,
                "login failed", Toast.LENGTH_SHORT).show();
    }
}
这里,Activity实现IUserLoginView接口,没啥好说的,直接实现就行了,还有就是Layout布局文件, 跟前面MVC的一样,也不再贴出来了。

(三)Presenter
Presenter是用作Model和View的桥梁,那么它又是怎么搭桥的呢?
主要也就是将UserHttpImp处理返回的结果,反馈到View上, OK, 下面继续看代码
//Presenter 完成ViewModel的交互
public class UserLoginPresenter {
    private IUserHttp userHttp;
    private IUserLoginView userLoginView;

    public UserLoginPresenter(IUserLoginView userLoginView, IUserHttp userHttp) {
        this.userLoginView = userLoginView;
        this.userHttp = userHttp;
    }

    public void login() {
        userLoginView.showLoading();
        userHttp.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnResultListener<User>() {
            @Override
            public boolean onResult(final int state, List<User> data, final User user) {
                if (state == OnResultListener.STATE_SUCCEED) {
                    userLoginView.toMainActivity(user);
                    userLoginView.hideLoading();
                } else {
                    userLoginView.showFailedError();
                    userLoginView.hideLoading();
                }
                return false;
            }
        });
    }
}
注意看代码, Presenter所做的事情,就是从View中获取需要的参数,再交给Model去执行业务方法,再将业务执行的结果反馈到View上。

OK, 到这,MVP也已经分析的差不多了, 最后再来总结下, 对比一下MVC 和 MVP
从 MVC  >   MVP,从代码上来看,代码量增多了,不过代码更清晰了,模块间的耦合度大大降低了。减轻了Activity的责任和代码量。

好的,只要学不死,就往死里学。接下来,继续下一篇 《浅谈Android中MVC、MVP、MVVM模式(三)》

以上是个人学习的一些整理,纯属个人见解,欢迎讨论和吐槽~


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值