Android MVP开发模式解析

MVP(Model-View-Presenter),Model提供数据,View界面显示,Presenter业务逻辑处理

MVP从经典的模式MVC演变而来,其主要优点是变成面向接口开发。即把UI视图逻辑提取到View接口处理,把业务逻辑提取到Presenter接口中处理,而View不能直接对Model进行操作,所有的交互都发生在Presenter内部,让Presenter从Model中获取数据后再处理最终返回给View显示,当然Presenter与Mode和View的沟通也都是通过接口进行的,目的是简化Activity中代码、职责单一、提高阅读性、降低耦合。

MVP和MVC的区别

MVP模型
这里写图片描述
Model: 实体模型,数据源
View: 对应于Activity,负责UI的绘制和用户的交互
Presenter: View和Mode沟通的桥梁以及业务逻辑处理

特点
View不能直接对Model进行操作,必须通过Presenter进行中转

MVC模型
这里写图片描述
Model:实体模型,数据源
View:布局文件
Controllor:对应于Activity

特点
View可以与Model直接交互

MVP优缺点

MVP的优点

  • 降低耦合度
  • 模块职责划分明显
  • 结构清晰,代码灵活,维护方便
  • 提高阅读性
  • 方便测试

缺点

  • 类比较多

使用示例-获取验证码

创建一个总体协调器,包括Model、View、Presenter各接口

public interface CodeContract {

    interface CodePresenter extends BasePresenter {
        /**
         * 提交验证码信息
         */
        void submitCodeInfo(String phone);
    }

    interface CodeView extends BaseView {

        /**
         * 获取验证码成功
         */
        void obtainCodeSuccess(String response);

        /**
         * 获取验证码失败
         */
        void obtainCodeFailure(String msg);
    }

    interface CodeModel {

        /**
         * 获取验证码网络数据
         */
        void getCodeInfo(String phone, OnListener onListener);
    }
}

Base类

/**
 * Created by yunzhao.liu on 2017/12/22
 */
public interface BasePresenter {

    /**
     * Activity销毁时,销毁各对象
     * 避免Activity内存泄漏
     */
    void onDestroy();

}


/**
 * Created by yunzhao.liu on 2017/12/22
 */

public interface BaseView {

    /**
     * 获取当前控件的Context
     */
    Context getContext();

    /**
     * 网络是否可用
     */
    boolean isNetConnect();

    /**
     * 显示加载框
     */
    void showLoading();

    /**
     * 隐藏加载框
     */
    void hideLoading();
}

网络请求成功、失败接口

public interface OnListener {

    /**
     * 请求网络成功
     * @param response 请求的数据
     */
    void onSuccess(String response);

    /**
     * 请求网络失败
     * @param msg 失败提示
     */
    void onFailure(String msg);
}

ObtainCodePresenter 负责View和Model的交互

/**
 * Created by yunzhao.liu on 2017/12/22
 * 负责View和Model的交互
 */
public class ObtainCodePresenter implements CodeContract.CodePresenter {

    private CodeContract.CodeView mView;
    private CodeContract.CodeModel mModel;

    public ObtainCodePresenter(CodeContract.CodeView view) {
        this.mView = view;
        mModel = new ObtainCodeModel();
    }

    @Override
    public void submitCodeInfo(String phone) {
        if (mView == null) return;
        mView.showLoading();
        mModel.getCodeInfo(phone, new OnListener() {

            @Override
            public void onSuccess(String response) {
                if (mView == null) return;
                mView.hideLoading();
                mView.obtainCodeSuccess(response);
            }

            @Override
            public void onFailure(String msg) {
                if (mView == null) return;
                mView.hideLoading();
                mView.obtainCodeFailure(msg);
            }
        });
    }

    @Override
    public void onDestroy() {
        mView = null;
    }
}

ObtainCodeModel 数据源 提供数据

/**
 * Created by yunzhao.liu on 2017/12/22
 * 数据源 提供数据
 */

public class ObtainCodeModel implements CodeContract.CodeModel {

    @Override
    public void getCodeInfo(String phone, final OnListener onListener) {
        //这里就在UI线程执行
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Random random = new Random();
                int code = random.nextInt(10000);
                if (true) {
                    onListener.onSuccess(code + "");
                } else {
                    onListener.onFailure("失败");
                }
            }
        }, 5000);
    }
}

Activity调用

public class MainActivity extends AppCompatActivity implements CodeContract.CodeView{

    private Button mBtn1;
    private CodeContract.CodePresenter mCodePresenter;
    private ProgressBar mPb;

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

    private void initView() {
        mBtn1 = findViewById(R.id.btn1);
        mPb = findViewById(R.id.pb);
    }

    private void initClick() {
        mBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                click1Btn();
            }
        });
    }

    private void click1Btn() {
        mCodePresenter.submitCodeInfo("111222333444");
    }

    private void initPresenter() {
        mCodePresenter = new ObtainCodePresenter(this);
    }

    @Override
    public void obtainCodeSuccess(String response) {
        mPb.setVisibility(View.GONE);
        Toast.makeText(this, response, Toast.LENGTH_SHORT).show();
    }

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

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public boolean isNetConnect() {
        return false;
    }

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

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

    @Override
    protected void onDestroy() {
        mCodePresenter.onDestroy();
        super.onDestroy();
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.cn.lyz.demom.MainActivity">

    <Button
        android:id="@+id/btn1"
        android:text="获取验证码"
        android:layout_width="match_parent"
        android:layout_centerVertical="true"
        android:layout_height="80dp"/>

    <ProgressBar
        android:id="@+id/pb"
        style="?android:attr/progressBarStyleInverse"
        android:layout_width="80dp"
        android:layout_centerInParent="true"
        android:layout_above="@+id/btn1"
        android:visibility="gone"
        android:layout_height="80dp" />

</RelativeLayout>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值