Android 中如何使用MVP设计模式

做过java前端开发的开发人员对mvc设计模式都不陌生,MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部。

在MVP模式里通常包含4个要素:

  1. View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
  2. View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
  3. Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
  4. Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
那么 ,为什么要使用设计模式呢? 

 在Android开发中,Activity的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的 职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter处理).

     另外,回想一下你在开发Android应用时是如何对代码逻辑进行单元测试的?是否每次都要将应用部署到Android模拟器或真机上,然后通过模拟用 户操作进行测试?然而由于Android平台的特性,每次部署都耗费了大量的时间,这直接导致开发效率的降低。而在MVP模式中,处理复杂逻辑的 Presenter是通过interface与View(Activity)进行交互的,这说明了什么?说明我们可以通过自定义类实现这个 interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试的时间。


我是感同身受,前段时间,做了一个小应用 ,由于没有合理的分层 ,导致activitiy 过于臃肿,如果没有详细的注释,可能过几月自己都不认识了
不过项目还是很好的,可以体验一下 ,豌豆荚下载地址:http://www.wandoujia.com/apps/com.ayit.weibo


首先,
MVP模式的m(模型)层:
封装一些数据,具有我们实际业务逻辑的要实现的方法

<span style="font-size:14px;">package com.ayit.mvpmodel.model;

import com.ayit.mvpmodel.listener.IStatusCallback;

/**
 * Created by Sweetheart on 2015/11/2 19:29.
 * Email: 378398018@qq.com
 * <br/>
 * MVP模式的m(模型)层。
 * 登陆状态,登陆的实际逻辑实现它去完成。
 */
public interface ILoginStatus extends  IStatus {

    public static final int STATUS_VERIFY_FAIL = -1;//验证失败
    public static final int STATUS_LOGIN_FAIL = -2;//登陆失败
    public static final int STATUS_LOGIN_SUCCESS = 0;//登陆成功
    public static final int STATUS_LOGIN_ING = 1;//登陆中


    /**
     * 登陆
     * @param account
     * @param psw
     * @return 状态码
     */
    public void login(String account,String psw,IStatusCallback callback);

}</span><span style="font-size: 24px;">
</span>




IStatus接口放一些公共的东西,这里并没有没什么东西,真正的实现类:

package com.ayit.mvpmodel.model.impl;

import android.os.AsyncTask;
import android.text.TextUtils;

import com.ayit.mvpmodel.listener.IStatusCallback;
import com.ayit.mvpmodel.model.ILoginStatus;

/**
 * Created by Sweetheart on 2015/11/2 19:32.
 * Email: 378398018@qq.com
 * <br/>
 * 实现类,处理数据
 */
public class LoginStatus implements ILoginStatus {
    private int status = ILoginStatus.STATUS_LOGIN_ING;
    private String msg = "";

    @Override
    public void login(final String account, final String psw,
                      final IStatusCallback callback) {
        new AsyncTask<String, Void, ILoginStatus>() {
            @Override
            protected ILoginStatus doInBackground(String... arg0) {
                if (varify(account, psw)) {
                    try {//模拟网络请求耗时处理
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if ("mvpmodel".equals(account) && "mvp".equals(psw)) {
                        status = ILoginStatus.STATUS_LOGIN_SUCCESS;
                        msg = "Success";
                    } else {
                        status = ILoginStatus.STATUS_LOGIN_FAIL;
                        msg = "Failed";
                    }
                }
                return LoginStatus.this;
            }

            @Override
            protected void onPreExecute() {
                callback.onStatus(LoginStatus.this);

            }

            @Override
            protected void onPostExecute(ILoginStatus result) {
                callback.onStatus(result);
            }
        }.execute();

    }

    /**
     * 本地校验
     * @param account
     * @param psw
     * @return
     */
    private boolean varify(String account, String psw) {
        if (TextUtils.isEmpty(account)) {
            status = ILoginStatus.STATUS_VERIFY_FAIL;
            msg = "Username cannot be empty";
            return false;
        }
        if (TextUtils.isEmpty(psw)) {
            status = ILoginStatus.STATUS_VERIFY_FAIL;
            msg = "Password cannot be empty";
            return false;
        }
        return true;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

MVP模式的V(视图)层
 * 这是一个抽象的登陆视图,里面都是一些界面动作,想要执行这些动作的界面都会去实现它。


package com.ayit.mvpmodel.view;

/**
 * Created by Sweetheart on 2015/11/2 19:36.
 * Email: 378398018@qq.com
 * <br/>
 * MVP模式的V(视图)层
 * 这是一个抽象的登陆视图,里面都是一些界面动作,想要执行这些动作的界面都会去实现它。
 */
public interface ILoginView extends  IView {
    /**
     * 弹出提示信息。
     */
    public void showMsg(String msg);
    /**
     * 成功登陆跳转主页。
     */
    public void moveToMain();
    /**
     * 加载中
     */
    public void showLoadding();
    /**
     * 隐藏
     */
    public void hideLoadding();
}



activity了实现实现ILoginView,包办一切的ui的操作,

package com.ayit.mvpmodel;

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

import com.ayit.mvpmodel.presenter.LoginPersenter;
import com.ayit.mvpmodel.view.ILoginView;

public class MainActivity extends AppCompatActivity  implements ILoginView,
        View.OnClickListener {
    private ProgressDialog dialog;
    private EditText etAccount, etPsw;
    private Button btnLogin;
    private LoginPersenter mPersenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPersenter = new LoginPersenter(this);
        initViews();
    }

    @Override
    public void showMsg(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void moveToMain() {
        Intent toMain = new Intent(this, MainActivity.class);
        startActivity(toMain);
    }

    @Override
    public void showLoadding() {
        dialog.show();
    }

    @Override
    public void hideLoadding() {
        dialog.cancel();
    }


    public void initViews() {
        dialog = new ProgressDialog(this);
        dialog.setMessage("加载中。。。");
        etAccount = (EditText) findViewById(R.id.et_account);
        etPsw = (EditText) findViewById(R.id.et_psw);
        btnLogin = (Button) findViewById(R.id.btn_login);
        btnLogin.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
            case R.id.btn_login:
                mPersenter.didLoginSuccess(etAccount.getText().toString(), etPsw
                        .getText().toString());
                break;

            default:
                break;
        }
    }

}


最后,就是MVP模式中的Persenter了,它负责主导所有的模型和视图

package com.ayit.mvpmodel.presenter;

import com.ayit.mvpmodel.listener.IStatusCallback;
import com.ayit.mvpmodel.model.ILoginStatus;
import com.ayit.mvpmodel.model.IStatus;
import com.ayit.mvpmodel.model.impl.LoginStatus;
import com.ayit.mvpmodel.view.ILoginView;

/**
 * Created by Sweetheart on 2015/11/2 19:41.
 * Email: 378398018@qq.com
 * <br/>
 * MVP模式中的P(主导器),它负责主导所有的模型和视图。
 */
public class LoginPersenter {
    private ILoginView mLoginView;// 持有视图对象
    private ILoginStatus mStatus;// 持有模型

    public LoginPersenter(ILoginView mLoginView) {
        mStatus = new LoginStatus();
        this.mLoginView=mLoginView;
    }
    public void didLoginSuccess(String account, String psw) {
        mStatus.login(account, psw, new IStatusCallback() {

            @Override
            public void onStatus(IStatus status) {
                LoginStatus s = (LoginStatus) status;
                switch (s.getStatus()) {
                    case ILoginStatus.STATUS_VERIFY_FAIL:// 验证失败
                    case ILoginStatus.STATUS_LOGIN_FAIL:// 登陆失败
                        mLoginView.hideLoadding();
                        mLoginView.showMsg(s.getMsg());
                        break;
                    case ILoginStatus.STATUS_LOGIN_ING:// 登陆中
                        mLoginView.showLoadding();
                        break;
                    case ILoginStatus.STATUS_LOGIN_SUCCESS:// 登陆成功
                        mLoginView.hideLoadding();
                        mLoginView.moveToMain();
                        break;
                    default:
                        break;
                }
            }
        });
    }
}


以上,我也是看网上别人的介绍及自己总结出来的,希望对你们有帮助。

如果你觉得对你有帮助,就在github上给个start吧

源码下载地址:点击打开链接  https://github.com/sweethearting/MVPModel


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值