安卓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生成的
获取新闻的逻辑接口INewsDao:
网络请求采用OkHttp:
(2)View层
Presenter与View交互是通过接口。所以我们这里需要定义一个INewsView,通过里面的接口方法来执行对View的操作。
作为View层,最重要的当然是Activity,MVP模式中Activity也是作为View层一部分。
(3)Presenter
Presenter用于处理Model与View的交互,类似MVC中的Controller层,数据获取到了,就应该展示在View。
首先定义一个IBasePresenter用来封装一些通用的方法,例如关联Activity的生命周期,在各个方法用户可以自己定义自己想要做的事。
注意到,Presenter里面有Model层和View层 的实现类:NewsDaoImpl和INewsView,这就是Presenter的作用,从View中获取需要的数据,交给Model去执行业务方法,执行的过程中需要的反馈以及结果,让View进行对应的显示。
好了,完整的代码结构讲完了,大家可以在https://github.com/GdinKing/MVPDemo下载源码。
希望大家能对MVP有更深的认识。
对于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
- 安卓MVP设计模式
- 简单介绍GUI设计模式(MVP)
- 理解MVC,MVP,MVVM设计模式的区别
- 大规模应用的开发与MVP设计模式
- 设计模式之架构型MVC,MVP,MVVM模式
- 探索MVP(Model-View-Presenter)设计模式在SharePoint平台下的实现
- 设计模式:Model View Presenter(MVP)
- ASP.NET 设计模式 MVP
- ASP.NET 设计模式(微软程序经理,MVP作序推荐)
- 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- [Composite UI][设计模式]MVP or MVC?
- MVP 设计模式在 SharePoint Workflow 中的应用
- 简单介绍GUI设计模式(MVP)
- 这样设计是MVP模式吗
- 简单介绍GUI设计模式(MVP)
- 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
- MVC设计模式或MVP设计模式-区别是什么?
- 安卓中实现情景模式的设计
- 安卓常用设计模式