MVP框架搭建
说到MVP,在网上查找了很多相关的资料,基本上是看得时候模模糊糊,然后过段时间就忘记了,如今空闲下来就来简单记录一下这个MVP吧。
网上都喜欢拿着MVP和MVC之间比较,然后就会有两张图,我反正是第一次看到时候是懵逼的,就像背书一样记下来(全是为了面试),后来随着代码量的增加,然后逐渐对这些有了新的认识,网上再多东西都是别人的,只有当自己理解了才是属于自己的。
基本都是这两张图,然而没什么卵用,对于MVC这个模式,就是基本没有啥思想,高兴就好,基本业务逻辑全在Activity(Fragment)这样写多了问题自然也就出现了,一个页面代码量巨长,然后某一天让你去改两个月前的一个页面中的某一个点的时候,突然发现,找都要找一会,这样就蛋疼了,而且发现很多相同的东西每个页面都要写一下,很明显的就是相同的网络请求,这样也很不爽,页面多了,同样的网络请求就会在好多个页面都会写一遍,因此我觉得应该引入MVP了,我对于MVP的理解不太向上面那个图一样,总而言之,高兴就好。
Activity 和Fragment 视为View层,负责处理 UI。Presenter 为业务处理层,既能调用UI逻辑,又能请求数据,该层为纯Java类,不涉及任何Android API。Model 层中包含着具体的数据请求,数据源。
三层之间调用顺序为View->Presenter->Model,那么问题就来了,我的处理是,那么Presenter和Model之间怎么连接起来的呢?我选择的是CallBack,View和Presenter之间我用的就是iView,iView这个东西就是基本MVP的标配了,这个CallBack就自己脑袋想想,实际上跟iView是差不多的东西,详情请看下面讲解
Callback
将信息从Model反馈给Presenter,这里写的是网络请求的反馈。在实际情况中可根据项目情况修改
public interface Callback<T> {
/**
* 数据请求成功
*
* @param data 请求到的数据
*/
void onSuccess(T data);
/**
* 使用网络API接口请求方式时,虽然已经请求成功但是由
* 于msg的原因无法正常返回数据。
*/
void onFailure(String msg);
/**
* 请求数据失败,指在请求网络API接口请求方式时,出现无法联网、
* 缺少权限,内存泄露等原因导致无法连接到请求数据源。
*/
void onError();
/**
* 当请求数据结束时,无论请求结果是成功,失败或是抛出异常都会执行此方法给用户做处理,通常做网络
* 请求时可以在此处隐藏“正在加载”的等待控件
*/
void onComplete();
}
Model
这里就可以写我们请求网络的接口方法,我下面是利用postDelayed来模拟的数据请求。然后通过callback将数据丢出去。
public class MvpModel {
/**
* 获取网络接口数据
* @param param 请求参数
* @param callback 数据回调接口
*/
public static void getNetData(final String param, final MvpCallback<String> callback){
// 利用postDelayed方法模拟网络请求数据的耗时操作
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switch (param){
case "normal":
callback.onSuccess(param+"参数请求成功了");
break;
case "failure":
callback.onFailure("请求失败");
break;
case "error":
callback.onError();
break;
}
callback.onComplete();
}
},1800);
}
}
Presenter
具体的业务逻辑类,根据网络请求的反馈进行处理,这里通过iView反馈给View(Activity/Fragment),下面我也用到了isViewAttach()方法,就是处理异步网络请求反馈回来数据,然后当前的页面消失掉了的处理,防止崩溃。然后需要View展示的各种结果也是在这里通过iView进行分发处理。
public class MvpPresenter extends BasePresenter<MvpView> {
/**
* 获取网络数据
*
* @param params 参数
*/
public void getData(String params) {
if (!isViewAttached()) {
//如果没有View引用就不加载数据
return;
}
//显示正在加载进度条
getView().showLoading();
// 调用Model请求数据
MvpModel.getNetData(params, new MvpCallback<String>() {
@Override
public void onSuccess(String data) {
//调用view接口显示数据
if (isViewAttached()) {
getView().showData(data);
}
}
@Override
public void onFailure(String msg) {
//调用view接口提示失败信息
if (isViewAttached()) {
getView().showToast(msg);
}
}
@Override
public void onError() {
//调用view接口提示请求异常
if (isViewAttached()) {
getView().showErr();
}
}
@Override
public void onComplete() {
// 隐藏正在加载进度条
if (isViewAttached()) {
getView().hideLoading();
}
}
});
}
}
iView
也就是定义一些方法,需要presenter反馈回来的方法,在View中接收然后处理,下面粘出来base的处理,不同的View的处理就各自继承然后自己定义。
public interface IBaseView {
/**
* 显示正在加载view
*/
void showLoading();
/**
* 关闭正在加载view
*/
void hideLoading();
/**
* 显示提示
* @param msg
*/
void showToast(String msg);
/**
* 显示请求错误提示
*/
void showErr();
}
Actiivty这下就省事多了,接收Presenter的反馈,然进行调用。唯一要注意的是添加View的引用和断开View的引用,一个在OnCreate(),一个在OnDestory()中。
public class MainActivity extends BaseActivity implements MvpView, View.OnClickListener {
private TextView tv_text;
MvpPresenter presenter;
private TextView tv_normal;
private TextView tv_failure;
private TextView tv_error;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_text = findViewById(R.id.tv_text);
tv_normal= findViewById(R.id.tv_normal);
tv_normal.setOnClickListener(this);
tv_failure=findViewById(R.id.tv_failure);
tv_failure.setOnClickListener(this);
tv_error=findViewById(R.id.tv_error);
tv_error.setOnClickListener(this);
//初始化Presenter
presenter = new MvpPresenter();
presenter.attachView(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//断开View引用
presenter.detachView();
}
@Override
public void showData(String data) {
tv_text.setText(data);
}
public void getData(View view) {
presenter.getData("normal");
}
public void getDataForFailure(View view) {
presenter.getData("failure");
}
public void getDataForError(View view) {
presenter.getData("error");
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_normal:
getData(tv_normal);
break;
case R.id.tv_failure:
getDataForFailure(tv_failure);
break;
case R.id.tv_error:
getDataForError(tv_error);
break;
}
}
}
好了一个完整的MVP就这么结束了。