MVP的一点理解

时间:2020-12-18 21:14:47

学习MVP已经有一段时间了,看了很多资料,也写了好几个demo,前段时间一直都在做项目,没时间总结一下,趁着这段时间没有那么忙了,把我学习的一些理解记录下来

总结起来就这张图
MVP的一点理解

举个我自己理解的例子
M和V在闹离婚,都不愿意和对方去沟通,这是后P就出现了,负责M和V的沟通工作…
V把离婚条件告诉P,P接到条件后就去问M,M考虑好条件告诉(接口回调给)P,P在去告诉V,V在做相应的处理.总结起来就是这个流程

自古文字留不住,总是代码得人心!下面开始撸代码

demo模拟刷新请求网络,显示请求的数据,看看目录
MVP的一点理解

1,首先要展示数据,是不是要一个JavaBean,那就建一个

package com.duanlian.mvpdemo.model;

import java.util.List;

/**
* 数据的javaBean
*/


public class DataBean {


private ShowapiResBodyBean showapi_res_body;
private int showapi_res_code;
private String showapi_res_error;

public ShowapiResBodyBean getShowapi_res_body() {
return showapi_res_body;
}

public void setShowapi_res_body(ShowapiResBodyBean showapi_res_body) {
this.showapi_res_body = showapi_res_body;
}

public int getShowapi_res_code() {
return showapi_res_code;
}

public void setShowapi_res_code(int showapi_res_code) {
this.showapi_res_code = showapi_res_code;
}

public String getShowapi_res_error() {
return showapi_res_error;
}

public void setShowapi_res_error(String showapi_res_error) {
this.showapi_res_error = showapi_res_error;
}

public static class ShowapiResBodyBean {
/**
* allNum : 29951
* allPages : 1498
* currentPage : 1
* maxResult : 20
* ret_code : 0
*/


private int allNum;
private int allPages;
private int currentPage;
private int maxResult;
private int ret_code;
private List<ContentlistBean> contentlist;

public int getAllNum() {
return allNum;
}

public void setAllNum(int allNum) {
this.allNum = allNum;
}

public int getAllPages() {
return allPages;
}

public void setAllPages(int allPages) {
this.allPages = allPages;
}

public int getCurrentPage() {
return currentPage;
}

public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}

public int getMaxResult() {
return maxResult;
}

public void setMaxResult(int maxResult) {
this.maxResult = maxResult;
}

public int getRet_code() {
return ret_code;
}

public void setRet_code(int ret_code) {
this.ret_code = ret_code;
}

public List<ContentlistBean> getContentlist() {
return contentlist;
}

public void setContentlist(List<ContentlistBean> contentlist) {
this.contentlist = contentlist;
}

public static class ContentlistBean {
/**
* ct : 2017-03-13 02:06:36.050
* id : 58c58e2c6e360f5dbfe2772f
* img : http://sc1.hao123img.com/data/3933e840a88aaee4a102dbc7987ab67b_0
* title : 跳高都能这么妖娆
* type : 2
*/


private String ct;
private String id;
private String img;
private String title;
private int type;

public String getCt() {
return ct;
}

public void setCt(String ct) {
this.ct = ct;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getImg() {
return img;
}

public void setImg(String img) {
this.img = img;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}
}
}
}

为啥要先建个bean呢,因为这个bean要在MVP3个中间传输的

2,创建一个请求Model数据成功失败的监听接口,这个接口是要回调到Presenter的,
创建一个Presenter收到请求成功或者失败后把结果传递给View层去做相应的处理的接口,
我这边是写在一个接口里(之所以这么写,因为别人都这么写,苦逼的我认为别人写的代码都很牛逼)

package com.duanlian.mvpdemo;

import com.duanlian.mvpdemo.model.DataBean;

/**
* view和model的接口
*/


public interface Contract {
//View的接口
interface View {
//成功后的回调去设置数据
void setInfo(DataBean dataBean);

//失败后的回调,去显示失败相关
void setError();
}

//Model的接口
interface Model {
//请求数据成功后的回调
void onSuccess(DataBean dataBean);

//请求数据失败后的回调
void onError();
}
}

3,创建一个请求数据的interface(也可以不创建,之所以创建时因为别人都创建了)参数1和2都是用来拼接地址的,参数3是用来返回请求结果的

package com.duanlian.mvpdemo.model;

import com.duanlian.mvpdemo.Contract;

/**
* 请求数据方法的接口
* 不用这个接口也行
*/


public interface GetData {
//传入一个请求数据的地址,一个请求的页数,一个请求结果的监听,成功失败都返回一个结果
void getData(String url, int page, Contract.Model model);
}

4,创建一个请求数据的类,实现刚才创建的接口

package com.duanlian.mvpdemo.model;

import com.duanlian.mvpdemo.Contract;
import com.google.gson.Gson;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import okhttp3.Call;

/**
* 用来请求和返回数据的类
*/


public class GetDataModel implements GetData{
@Override
public void getData(String url, int page, final Contract.Model model) {
OkHttpUtils.get()
.url(url + page)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
//把请求失败返回去
model.onError();
}

@Override
public void onResponse(String response, int id) {
Gson gson = new Gson();
DataBean dataBean = gson.fromJson(response, DataBean.class);
//请求成功把bean返回过去
model.onSuccess(dataBean);
}
});
}
}

5,接下来就是presenter了,注释很清楚了,就不啰嗦了

package com.duanlian.mvpdemo.presenter;

import com.duanlian.mvpdemo.Contract;
import com.duanlian.mvpdemo.model.DataBean;
import com.duanlian.mvpdemo.model.GetData;
import com.duanlian.mvpdemo.model.GetDataModel;

/**
* view和model的中间枢纽
*/


public class MyPresenter implements Contract.Model, GetData {
//既然Presenter是连接View和model的桥梁,所以他既有View的引用也有Model的引用
Contract.View mView;
GetDataModel mModel;

//构造方法把View传递过来
public MyPresenter(Contract.View view) {
this.mView = view;
mModel = new GetDataModel();

}

@Override
public void onSuccess(DataBean dataBean) {
//如果model里面请求数据成功就返回到这里,然后吧数据传递过去,通知View去展示相关数据
mView.setInfo(dataBean);
}

@Override
public void onError() {
//如果数据请求失败的话就通知View去显示失败后的相关
mView.setError();
}

@Override
public void getData(String url, int page, Contract.Model model) {
//通知model去请求数据,请求结果会返回到这里的onSuccess()和onError()
mModel.getData(url, page, this);
}
}

6,作为View层最轻松了,就是通知Presenter去请求网络,然后就是等待数据的返回了

package com.duanlian.mvpdemo;

import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import android.widget.Toast;

import com.duanlian.mvpdemo.adapter.ListViewAdapter;
import com.duanlian.mvpdemo.model.DataBean;
import com.duanlian.mvpdemo.presenter.MyPresenter;

public class MainActivity extends AppCompatActivity implements Contract.View {
private ListView mListView;
private SwipeRefreshLayout mRefreshLayout;
private ListViewAdapter mAdapter;
private MyPresenter mPresenter;
private int page = 1;
private String url;


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

private void initView() {
mListView = (ListView) findViewById(R.id.listview);
mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh);
//实例化Presenter,把View传递过去
mPresenter = new MyPresenter(this);
url = "http://route.showapi.com/341-2?maxResult=20&showapi_appid=28968&showapi_sign=4e30b3520be34fe09846cc2c3a3c203f&page=";
// mPresenter.getData(url, page, null);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//通知presenter去请求网络
mPresenter.getData(url, page, null);
}
});

}

@Override
public void setInfo(DataBean dataBean) {
if (dataBean != null) {
mRefreshLayout.setRefreshing(false);
mAdapter = new ListViewAdapter(this, dataBean);
mListView.setAdapter(mAdapter);
}
}

@Override
public void setError() {
mRefreshLayout.setRefreshing(false);
Toast.makeText(this, "失败了", Toast.LENGTH_SHORT).show();
}
}

View层最重要的是把View的实例通过presenter的构造方法传递过去,然后就是等待presenter的返回了

我的理解大概就这么多了,后面有新的理解持续更新,
demo运行效果
MVP的一点理解

demo地址:点击下载