欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android MVP开发模式解析

程序员文章站 2022-05-12 15:27:03
...

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模型
Android MVP开发模式解析
Model: 实体模型,数据源
View: 对应于Activity,负责UI的绘制和用户的交互
Presenter: View和Mode沟通的桥梁以及业务逻辑处理

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

MVC模型
Android MVP开发模式解析
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>