Android MVP 实践之路(理解篇)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvzhongdi/article/details/80580312

一.简单介绍下MVP

1.什么是mvp?
简称:MVP 全称:Model-View-Presenter ;MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
2.mvp 与mvc 的区别?
在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
3.优点和缺点介绍
优点:
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
缺点:
由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。还有一点需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。

二.看下实现的效果图

三.接下来是代码实现的过程

1.从创建开始
第1步:打开Android Studio 然后新建一个工程;
第2步:在工程中,新建三个包,分个层,分别是modle、view、presenter
第3步:思考下我们要实现的功能,模拟网络请求,然后点击Button,实现页面上的TextView的文字改变,这中间我们用Handler模拟一下网络请求
第4步:思考一下我们在MVC的时候,Activity要实现的方法:
a.点击按钮请求数据
b.当数据请求成功后,调用此接口显示数据
c.当数据请求失败后,调用此接口提示
d.当数据请求异常,调用此接口提示
e.显示正在加载进度框
f.隐藏正在加载进度框
第5步:根据上面分析在MVC中所要实现的方法,我们来实现在MVP的View层的接口中需要实现这几个方法;
public interface MvpView {
/**
 * 显示正在加载进度框
 */
void showLoading();
/**
 * 隐藏正在加载进度框
 */
void hideLoading();
/**
 * 当数据请求成功后,调用此接口显示数据
 * @param data 数据源
 */
void showData(String data);
/**
 * 当数据请求失败后,调用此接口提示
 * @param msg 失败原因
 */
void showFailureMessage(String msg);
/**
 * 当数据请求异常,调用此接口提示
 */
void showErrorMessage();

}

第6步:我们的View层好像写好了,接下来我们来想想我们的model层吧。其实很简单,我们说了model层是数据获取传输的层,那么在model中创建个model类,然后写一个获取数据的静态方法,这是获取到数据了,那么我们获取到的数据怎么传递给我们的Presenter呢? 不饶了,利用接口Callback方法来进行数据的回调;两段代码如下:

MvpModel类

public class MvpModel {
/**
 * 获取网络接口数据
 *
 *
 * @param param    请求参数
 * @param callback 数据回调接口
 */
public static void getNetData(final String param, final MvpCallback callback) {
    // 利用postDelayed方法模拟网络请求数据的耗时操作
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            callback.onSuccess("模拟网络请求得到的数据");
            callback.onComplete();
        }
    }, 2000);
}
}

MvpCallback类

public interface MvpCallback {
/**
 * 数据请求成功
 *
 * @param data 请求到的数据
 */
void onSuccess(String data);

/**
 * 使用网络API接口请求方式时,虽然已经请求成功但是由
 * 于{@code msg}的原因无法正常返回数据。
 */
void onFailure(String msg);

/**
 * 请求数据失败,指在请求网络API接口请求方式时,出现无法联网、
 * 缺少权限,内存泄露等原因导致无法连接到请求数据源。
 */
void onError();

/**
 * 当请求数据结束时,无论请求结果是成功,失败或是抛出异常都会执行此方法给用户做处理,通常做网络
 * 请求时可以在此处隐藏“正在加载”的等待控件
 */
void onComplete();

}
第7步:如上方法实现后,那我们的View和model层都有了,我们要实现presenter层,这个是作为中间转换成,要实现model层和view层的方法;所以要传递一个实现View接口的窗口视图进来,然后调用model层的数据获取方法,将model层的数据展示给我我们的view哦;啥都不说了,代码看一眼就懂了;

MvpPresenter 类

public class MvpPresenter {
// View接口
private MvpView mView;

public MvpPresenter(MvpView view) {
    this.mView = view;
}
/**
 * 获取网络数据
 *
 * @param params 参数
 */
public void getData(String params) {
    //显示正在加载进度条
    mView.showLoading();
    // 调用Model请求数据
    MvpModel.getNetData(params, new MvpCallback() {
        @Override
        public void onSuccess(String data) {
            //调用view接口显示数据
            mView.showData(data);
        }

        @Override
        public void onFailure(String msg) {
            //调用view接口提示失败信息
            mView.showFailureMessage(msg);
        }

        @Override
        public void onError() {
            //调用view接口提示请求异常
            mView.showErrorMessage();
        }

        @Override
        public void onComplete() {
            // 隐藏正在加载进度条
            mView.hideLoading();
        }
    });
}
}
第8步:是不是很刺激?看看自己都写了什么❓,下面就是见证奇迹的时刻,我们的mainActivity中应该如何编写?布局文件很简单,就是一个线性布局,里面一个Button,一个TextView;在Activity中,要实例化Presenter类,并且那几个方法都在Presenter中实现了哦,在来一个dialog展示框就行了,对不对?上代码看看吧,会好理解一些;

MainActivity 类

public class MainActivity extends AppCompatActivity implements MvpView {

private ProgressDialog progressDialog;
private MvpPresenter presenter;
private TextView textview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textview = findViewById(R.id.textview);
    progressDialog = new ProgressDialog(this);
    progressDialog.setCancelable(false);
    progressDialog.setMessage("正在加载数据");
    presenter = new MvpPresenter(this);

}

/**
 * 点击事件
 * @param view
 */
public void getDatas(View view) {
    presenter.getData("normal");
}

/**
 * 显示正在加载进度框
 */
@Override
public void showLoading() {
    if (!progressDialog.isShowing()) {
        progressDialog.show();
    }
}

/**
 * 隐藏正在加载进度框
 */
@Override
public void hideLoading() {
    if (progressDialog.isShowing()) {
        progressDialog.dismiss();
    }
}

/**
 * 当数据请求成功后,调用此接口显示数据
 *
 * @param data 数据源
 */
@Override
public void showData(String data) {
    textview.setText(data);
}

/**
 * 当数据请求失败后,调用此接口提示
 *
 * @param msg 失败原因
 */
@Override
public void showFailureMessage(String msg) {
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}

/**
 * 当数据请求异常,调用此接口提示
 */
@Override
public void showErrorMessage() {
    Toast.makeText(this, "网络请求数据出现异常", Toast.LENGTH_SHORT).show();
}

}

四.如上就是实现的过程,这是一个简单的demo,帮助我们理解和熟悉MVP到底是什么玩意,真的想要在项目中实践,还需要花费一番功夫来弄。这个简单的demo先分享给大家,更多的MVP的内容,我会在下面的文章中更新,欢迎大家一起交流,感谢大家;

最后附上一个GitHub的 下载地址
喜欢的也可以关注下我的微信公众号“七秒的空间”

猜你喜欢

转载自blog.csdn.net/lvzhongdi/article/details/80580312