您的位置:首页 > 移动开发 > Android开发

安卓MVP设计模式

2017-03-10 15:27 288 查看
一、概述

对于MVP设计模式,我相信大部分安卓开发者都应该听过,可到底MVP是怎么样的,或许很多人也没有实践过,今天,我就带大家走进MVP的使用。

1、MVP是什么?

Model-view-presenter,简称MVP,是软件设计中一种对针对MVC模式,再审议后所延伸提出的一种软件设计模式。

MVP的使用有助于实现程序结构分离,解耦。

Model 定义程序的业务逻辑和实体模型。

View 视图层,用以展示来自Model的信息以及经过Presenter对事件处理后的信息,对应于布局文件、Activity和Fragment。

Presenter 包含着事件逻辑处理,负责从Model层获取信息,并将取得的信息经过格式转换与View进行通讯。

2、MVP与MVC的区别

MVC

Model:定义程序的业务逻辑和实体模型。

View:视图层,对应于布局文件。

Controller:业务逻辑层,主要是Activity和Fragment。

MVC里View对应于布局文件,其实做的事情仅仅是展示控件,实际上数据绑定的操作,事件处理的代码都在Activity或Fragment中,造成了Activity或Fragment既承担了View的功能又承担了Controller的功能,MVC还允许Model与View进行交互。

而在MVP中,Presenter的出现,将Actvity/Fragment作为View层,Presenter负责完成View层与Model层的交互,这样做的好处是程序代码耦合度更低,更容易测试,结构更清晰。但随之也带来一个问题:类的数量过于庞大。

二、案例

本案例,我实现了一个请求网络新闻的功能。下面来介绍MVP在其中的应用。

包结构:



(1)Model层

News实体类,我是通过GsonFormat生成的

public class News {

private String error_code;
private String reason;
private List<ResultBean> result;

public String getErrorCode() {
return error_code;
}

public void setErrorCode(String error_code) {
this.error_code = error_code;
}

public String getReason() {
return reason;
}

public void setReason(String reason) {
this.reason = reason;
}

public List<ResultBean> getResult() {
return result;
}

public void setResult(List<ResultBean> result) {
this.result = result;
}

public static class ResultBean {

private String title;
private String content;
private String img_width;
private String full_title;
private String pdate;
private String src;
private String img_length;
private String img;
private String url;
private String pdate_src;

public String getTitle() {
return title;
}

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

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public String getImg_width() {
return img_width;
}

public void setImg_width(String img_width) {
this.img_width = img_width;
}

public String getFull_title() {
return full_title;
}

public void setFull_title(String full_title) {
this.full_title = full_title;
}

public String getPdate() {
return pdate;
}

public void setPdate(String pdate) {
this.pdate = pdate;
}

public String getSrc() {
return src;
}

public void setSrc(String src) {
this.src = src;
}

public String getImg_length() {
return img_length;
}

public void setImg_length(String img_length) {
this.img_length = img_length;
}

public String getImg() {
return img;
}

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

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getPdate_src() {
return pdate_src;
}

public void setPdate_src(String pdate_src) {
this.pdate_src = pdate_src;
}
}

}


获取新闻的逻辑接口INewsDao:

public interface INewsDao {
void getNews(String key,OnDataGetListener listener);
}


public class NewsDaoImpl implements INewsDao {

public static final String BASE_URL = " http://apis.haoservice.com/lifeservice/news?"; public static final String APP_KEY = "6a74ccfde5e04f27b344718ba923fe3f";

/**
* 请求新闻数据的具体实现方法
* @param keyWords  关键词
* @param listener  请求结果回调接口
*/
@Override
public void getNews(String keyWords, final OnDataGetListener listener) {
try {
keyWords = URLEncoder.encode(keyWords, "utf-8");

StringBuilder sb = new StringBuilder();
sb.append(BASE_URL);
sb.append("key=");
sb.append(APP_KEY);
sb.append("&q=");
sb.append(keyWords);

//创建一个请求
final Request request = new Request.Builder().url(sb.toString()).build();
//创建一个Call
final Call call = HttpHelper.getInstance().getOkHttpClient().newCall(request);

//执行请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (listener != null) {
listener.onError();
}
}

@Override
public void onResponse(Call call, Response response) throws IOException {
if (listener != null) {
listener.onSuccess(response.body().string());
}
}
});

} catch (Exception e) {
e.printStackTrace();
}
}

}


网络请求采用OkHttp:

public class HttpHelper {

private static HttpHelper mInstance;
private static OkHttpClient mOkHttpClient;

private HttpHelper() {
//初始化OkHttpClient
mOkHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)//设置超时时间
.readTimeout(10, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(10, TimeUnit.SECONDS)//设置写入超时时间
.build();
}

public static HttpHelper getInstance() {
if (mInstance == null) {
synchronized (HttpHelper.class) {
if (mInstance == null) {
mInstance = new HttpHelper();
}
}
}
return mInstance;
}

public OkHttpClient getOkHttpClient() {
return mOkHttpClient;
}

}


(2)View层

Presenter与View交互是通过接口。所以我们这里需要定义一个INewsView,通过里面的接口方法来执行对View的操作。

/**
* 通用的View模块,可以在这里写一些公用的接口方法
* @author king
* @date 2017/3/10 10:23
*/
public interface IViewBinder {
}


//开发人员可以根据实际需求扩展该接口,增加其他操作View的方法。
public interface INewsView extends IViewBinder {

void showProgress();//显示进度条

void hideProgress();//隐藏进度条

void onSuccess(String response);//请求成功

void onError();//请求失败
}


作为View层,最重要的当然是Activity,MVP模式中Activity也是作为View层一部分。

public class MainActivity extends AppCompatActivity implements INewsView {

private ProgressDialog mProgressDialog;

private Button btn_get;
private TextView tv_data;

private NewsPresenter mNewsPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn_get = (Button) findViewById(R.id.btn_get);
tv_data = (TextView) findViewById(R.id.tv_data);

mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("加载中");
mNewsPresenter = new NewsPresenter(this);
btn_get.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mNewsPresenter.getNews("三星电视变CIA窃听器");
}
});
}

@Override
public void showProgress() {
mProgressDialog.show();
}

@Override
public void hideProgress() {
mProgressDialog.dismiss();
}

@Override
public void onSuccess(String response) {
try {
News news = parseJson(response);
String code = news.getErrorCode();
if("0".equals(code)) {
String text = news.getResult().get(0).getTitle()+"\n\n"+news.getResult().get(0).getContent();
tv_data.setText(text);
}else{
Toast.makeText(this,news.getReason(),Toast.LENGTH_SHORT).show();
}
}catch (Exception e){

}
}

@Override
public void onError() {
Toast.makeText(this,"请求数据失败",Toast.LENGTH_SHORT).show();
}

private News parseJson(String json) {
return new Gson().fromJson(json, News.class);
}
}


(3)Presenter

Presenter用于处理Model与View的交互,类似MVC中的Controller层,数据获取到了,就应该展示在View。

首先定义一个IBasePresenter用来封装一些通用的方法,例如关联Activity的生命周期,在各个方法用户可以自己定义自己想要做的事。

/**
* 基础的presenter,用于关联Activity或fragment生命周期
* @author king
* @date 2017/3/10 10:24
*/
public interface IBasePresenter {

void onCreate();

void onStart();

void onPause();

void onStop();

void onDestory();
}


public class NewsPresenter implements IBasePresenter{

private INewsView mNewsView;
private NewsDaoImpl newsDao;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 200:
mNewsView.onSuccess((String) msg.obj);//因为是异步,所以需要handler
break;
case 201:
mNewsView.onError();
break;
}
}
};

public NewsPresenter(INewsView view){
this.mNewsView = view;
this.newsDao = new NewsDaoImpl();
}

/**
* 获取新闻数据
* @param key
*/
public void getNews(String key){
mNewsView.showProgress();
newsDao.getNews(key, new OnDataGetListener() {
@Override
public void onSuccess(String response) {
mNewsView.hideProgress();
Message msg = Message.obtain();
msg.what = 200;
msg.obj = response;
mHandler.sendMessage(msg);
}

@Override
public void onError() {
mNewsView.hideProgress();
Message msg = Message.obtain();
msg.what = 201;
mHandler.sendMessage(msg);
}
});

}
@Override
public void onCreate() {

}

@Override
public void onStart() {

}

@Override
public void onPause() {

}

@Override
public void onStop() {

}

@Override
public void onDestory() {

}
}


注意到,Presenter里面有Model层和View层 的实现类:NewsDaoImpl和INewsView,这就是Presenter的作用,从View中获取需要的数据,交给Model去执行业务方法,执行的过程中需要的反馈以及结果,让View进行对应的显示。

好了,完整的代码结构讲完了,大家可以在https://github.com/GdinKing/MVPDemo下载源码。

希望大家能对MVP有更深的认识。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mvp 设计模式 android