学习MVP已经有一段时间了,看了很多资料,也写了好几个demo,前段时间一直都在做项目,没时间总结一下,趁着这段时间没有那么忙了,把我学习的一些理解记录下来
总结起来就这张图
举个我自己理解的例子
M和V在闹离婚,都不愿意和对方去沟通,这是后P就出现了,负责M和V的沟通工作…
V把离婚条件告诉P,P接到条件后就去问M,M考虑好条件告诉(接口回调给)P,P在去告诉V,V在做相应的处理.总结起来就是这个流程
自古文字留不住,总是代码得人心!下面开始撸代码
demo模拟刷新请求网络,显示请求的数据,看看目录
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运行效果
demo地址:点击下载