初识MVP

初识MVP

学习Android有一段时间了,一直以实现一些小功能的方式来学习。这样就导致了代码写的不怎么规范,以至于后来重新翻看自己的代码并且重构自己的项目的时候,被自己的代码恶心到了。
以至于后来学习了一些设计模式,以及架构工程的设计模式才得以改进。

话不多说,下面谈谈我学习MVP的过程以及我对MVP的理解。

谈及MVP,许多人都会先从MVC讲起。我认为这是很有必要的,因为MVP架构,就是因为MVC在Android无法更好解决问题的时候才提出的。那么什么是MVC,MVC有什么优缺点,为什么MVC在大型的Andorid项目中暴露出那么多缺点呢?

带着这几个问题,下面先来从新认识一下MVC架构

1、什么是MVC?

关于什么是MVC,网上有很多资料,我这里也不班门弄斧,简单的给大家进行介绍。
MVC即Model-View-Controller。M:逻辑模型,V:视图模型,C:控制器

逻辑模型(Model)

所谓逻辑模型,通俗的理解就是指业务逻辑层,同时对数据的操作的层,比如网络中请求一些数据、数据库中存取等

视图模型(View)

视图层,望文即可生义,视图层就是可以理解为展示给用户的界面,其中包括一系列View组件、布局、按钮等等。

控制层(Controller)

控制层是MVC中相对比较重要的一层,它负责协调M-V两层,在Android中,Activity就是一个典型的Controller,它即可响应View的事件,也可调用Model中的数据和方法,进而反馈到View层中

所以,MVC中,基本的流程就是,M负责数据的来源和处理,然后通过C将数据反馈到V。

2、MVC有什么优点?

MVC对于传统的应用是有着巨大的帮助与贡献的,为什么这么说?因为,在传统的应用中,MVC三层的划分可以让工程划分的更分析,同时,这样也可以实现层次间的解耦,以及提升开发的效率。在开发的过程中,只要相互间约定好接口,就可以各自开发而且互相之间不会有什么冲突。
另外,MVC的另一个优点就是简单。由于它的简单性,就可以让开发人员迅速掌握,并且很好的运用到工程中。

3.MVC为何在大型Android项目中会显得有点不太“适用”?

MVC在Android这个“特殊”的环境中有时会显得有点力不从心甚至还会出现拖后腿的现象。
在Android中,Activity通常就充当一个Controller的角色,但Activity还具有操作View的责任、响应View的事件以及响应自身生命周期的责任。这样一来,使得一个Activity的代码数量很容易上千甚至上万,如此一来,Activity就变得非常臃肿,变得不好维护和阅读。除此以外,C-V之间耦合度也就高了,甚至可以说是M和V重合在一起了。

基于上面的几个问题,我们就可以引出

MVP模式

看了上面几个问题,你可能会认为MVP的出现可能大概就是为了填MVC所挖的坑的吧。

MVP其实就是MVC的“进化版”,和MVC一样,MV都分别代表Model和View层,Presenter则是表示层。

下面用两个图来表示

上面可以看出,MVC中允许Model和View中进行交互,而在MVP中,把Layout布局和Activity作为View层,增加了Presenter层,利用Presenter和Model层进行业务交互,然后Presenter再与View层交互,从而避免了View与Modele之间相互联系的现象。出现这样的根本原因在于Presenter的出现让Activity的工作量减轻了不少,它把Controller的工作从Activity身上切了出来。

上面分析了一下MVP,接下来就是实现MVP的一个Demo

实现一个简单的登陆功能,包结构如下

1.准备一个User的实体类

package com.example.mvp.mvp.bean;
public class User {
    private String username ;
    private String password ;
    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

2.Model层

model层需要一个接口以及它的实现类

package com.example.mvp.mvp.model;


import com.example.mvp.mvp.bean.User;

public interface IUserBiz {
    void login(String username,String password,OnLoginListener loginListener);
    interface OnLoginListener {
        void loginSuccess(User user);
        void loginFailed();
    }
}

3.View层

View层只有一个接口

package com.example.mvp.mvp.view;


import com.example.mvp.mvp.bean.User;

public interface IUserLoginView {
    String getUserName();
    String getPassword();
    void clearPassword();
    void clearUserName();
    void showLoading();
    void hideLoading();
    void toMainActivity(User user);
    void showFailedError();
}

4.Presenter层

presenter层有一个实体类

package com.example.mvp.mvp.presenter;


import android.os.Handler;

import com.example.mvp.mvp.bean.User;
import com.example.mvp.mvp.model.IUserBiz;
import com.example.mvp.mvp.model.OnLoginListener;
import com.example.mvp.mvp.model.UserBiz;
import com.example.mvp.mvp.view.IUserLoginView;



public class UserLoginPresenter {
    private IUserBiz userBiz;//model层引用
    private IUserLoginView userLoginView;//View层引用
    private Handler mHandler = new Handler();

    public UserLoginPresenter(IUserLoginView userLoginView){
        this.userLoginView = userLoginView;
        this.userBiz = new UserBiz();
    }

    public void login(){
        userLoginView.showLoading();
        //模拟数据加载时的线程切换(View的操作需要放在主线程)
        userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void loginSuccess(final User user) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideLoading();
                    }
                });
            }

            @Override
            public void loginFailed() {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.showFailedError();
                        userLoginView.hideLoading();
                    }
                });
            }
        });
    }

    public void clear(){
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }
}

5.Activity

package com.example.mvp.mvp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.example.mvp.R;
import com.example.mvp.mvp.bean.User;
import com.example.mvp.mvp.presenter.UserLoginPresenter;
import com.example.mvp.mvp.view.IUserLoginView;

public class LoginActivity extends AppCompatActivity implements IUserLoginView{
    private EditText mEtUsername, mEtPassword;
    private Button mBtnLogin, mBtnClear;
    private ProgressBar mPbLoading;
    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);

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

    private void initView(){
        mEtUsername = (EditText) findViewById(R.id.et_userName);
        mEtPassword = (EditText) findViewById(R.id.et_password);

        mBtnClear = (Button) findViewById(R.id.bt_clear);
        mBtnLogin = (Button) findViewById(R.id.bt_login);

        mPbLoading = (ProgressBar) findViewById(R.id.progress);

        mBtnLogin.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mUserLoginPresenter.login();
            }
        });

        mBtnClear.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mUserLoginPresenter.clear();
            }
        });
    }
    @Override
    public String getUserName()
    {
        return mEtUsername.getText().toString();
    }

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

    @Override
    public void clearUserName()
    {
        mEtUsername.setText("");
    }

    @Override
    public void clearPassword()
    {
        mEtPassword.setText("");
    }

    @Override
    public void showLoading()
    {
        mPbLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading()
    {
        mPbLoading.setVisibility(View.GONE);
    }

    @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();
    }
}

分析、总结

由上面的代码大概可以看出MVP的基本思想,正如前面所说,MVP的出现是淡化了Activity在安卓中充当Controller这一角色的事实,更多的是把Activity归属到View层中,使得Activity的工作变得更轻松。当然,如果相对于小型的项目,Activity完全可以充当Controller的作用,因为在小型的项目中,Activity处理的东西会相对较少,此时用上MVP的架构可能会将一件简单的事情复杂化。

说明:上述代码是借鉴鸿洋大神的《浅谈 MVP in Android》一文完成,如有错误,敬请指出,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值