浅析android的mvp模式

 MPV 是从经典的MVC模式演变过来的,其基本思路都是相通的。

      MVP是模型(Model)、视图(View)、控制者(Presenter)的缩写,分别代表项目中3个不同的模块。

        模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;

        视图(View):负责界面数据的展示,与用户进行交互;

        控制者(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

      在Andorid项目中,我们习惯将Activity作为MVC中的控制者来达到Model模型和View视图分离,但是在MVP框架模式中,通常将Activity作为View视图层,因为在MVC框架模式中Activity和View视图显示关联紧密,Activity中包含大量的View视图显示代码,如果哪天老板说需要修改View视图显示,这时候你是不是感觉需要修改Activity中的大量代码?这么一来会将Activity中控制逻辑破坏,也导致Activity中承担太多的职责。根据单一职责原则,Activity主要起到用户交互作用,也就是接收用户输入,显示请求结果。因此可以通过MVP框架模式来减轻Activity的职责。

      如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。

      这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。

      我举一个获取天气的例子来说明,这样大家会很容易看懂

      Model模型

[java]  view plain  copy
  1. /** 
  2.  * 天气Model接口 
  3.  */  
  4. public interface WeatherModel {  
  5.     void loadWeather(String cityNO, OnWeatherListener listener);  
  6. }  
  7. .........  
  8. /** 
  9.  * 天气Model实现 
  10.  */  
  11. public class WeatherModelImpl implements WeatherModel {  
  12.     @Override  
  13.     public void loadWeather(String cityNO, final OnWeatherListener listener) {  
  14.         /*数据层操作*/  
  15.         VolleyRequest.newInstance().newGsonRequest("http://www.weather.com.cn/data/sk/" + cityNO + ".html",  
  16.                 Weather.classnew Response.Listener<weather>() {  
  17.                     @Override  
  18.                     public void onResponse(Weather weather) {  
  19.                         if (weather != null) {  
  20.                             listener.onSuccess(weather);  
  21.                         } else {  
  22.                             listener.onError();  
  23.                         }  
  24.                     }  
  25.                 }, new Response.ErrorListener() {  
  26.                     @Override  
  27.                     public void onErrorResponse(VolleyError error) {  
  28.                         listener.onError();  
  29.                     }  
  30.                 });  
  31.     }  
  32. }  

      和MVC一样,Model的代码不变,只是用与处理网络请求,请求成功后接口回调将Model模型处理的数据返回给Presenter控制者。

      Presenter控制器

[java]  view plain  copy
  1. /** 
  2.  * 天气 Presenter接口 
  3.  */  
  4. public interface WeatherPresenter {  
  5.     /** 
  6.      * 获取天气的逻辑 
  7.      */  
  8.     void getWeather(String cityNO);  
  9.    
  10. }  
  11. ..........  
  12.    
  13. /** 
  14.  * 在Presenter层实现,给Model层回调,更改View层的状态,确保Model层不直接操作View层 
  15.  */  
  16. public interface OnWeatherListener {  
  17.     /** 
  18.      * 成功时回调 
  19.      * 
  20.      * @param weather 
  21.      */  
  22.     void onSuccess(Weather weather);  
  23.     /** 
  24.      * 失败时回调,简单处理,没做什么 
  25.      */  
  26.     void onError();  
  27.    
  28. }  
  29. .........  
  30.   
  31. /** 
  32.  * 天气 Presenter实现 
  33.  */  
  34. public class WeatherPresenterImpl implements WeatherPresenter, OnWeatherListener {  
  35.     /*Presenter作为中间层,持有View和Model的引用*/  
  36.     private WeatherView weatherView;  
  37.     private WeatherModel weatherModel;  
  38.    
  39.     public WeatherPresenterImpl(WeatherView weatherView) {  
  40.         this.weatherView = weatherView;  
  41.         weatherModel = new WeatherModelImpl();  
  42.     }  
  43.    
  44.     @Override  
  45.     public void getWeather(String cityNO) {  
  46.         weatherView.showLoading();  
  47.         weatherModel.loadWeather(cityNO, this);  
  48.     }  
  49.    
  50.     @Override  
  51.     public void onSuccess(Weather weather) {  
  52.         weatherView.hideLoading();  
  53.         weatherView.setWeatherInfo(weather);  
  54.     }  
  55.    
  56.     @Override  
  57.     public void onError() {  
  58.         weatherView.hideLoading();  
  59.         weatherView.showError();  
  60.     }  
  61. }  

      从代码中我们可以看到Presenter控制器同时持有 WeatherModel和WeatherView对象且实现了OnWeatherListener接口取回Model模型数据,因此,WeatherPresenterImpl向WeatherModel发送数据请求,然后通过OnWeatherListener接口实现获取请求结果,在将结果通过接口WeatherView把数据显示到Activity担当的View视图中。从而达到彻底将Model和View完全分离,试想在这种情况下,如果你需要修改Model是完全不会影响View视图代码的修改的,同理,修改View视图层的时候,也完全无需修改Model层。相当于Model和View互相不知道对方的存在,都是通过中间控制器Presenter来传达通信。

      View视图

      先定义一个View视图显示的接口WeatherView

      新闻列表模块主要是展示从网络获取的新闻列表信息,View层的接口大概需要如下方法:

  (1)加载数据的过程中需要提示“正在加载”的反馈信息给用户

  (2)加载成功后,将加载得到的数据填充到RecyclerView展示给用户

  (3)加载成功后,需要将“正在加载”反馈信息取消掉

  (4)若加载数据失败,如无网络连接,则需要给用户提示信息

  根据上面描述,我们将View层的接口定义如下,分别对应上面四个方法:

[java]  view plain  copy
  1. public interface WeatherView {  
  2.     void showLoading();  
  3.    
  4.     void hideLoading();  
  5.    
  6.     void showError();  
  7.    
  8.     void setWeatherInfo(Weather weather);  
  9. }  
      然后实现Activity实现WeatherView接口
[java]  view plain  copy
  1. /** 
  2.  * 天气界面 
  3.  */  
  4. public class WeatherActivity extends BaseActivity implements WeatherView, View.OnClickListener {  
  5.     ..........................  
  6.     private WeatherPresenter weatherPresenter;  
  7.    
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.activity_main);  
  12.         init();  
  13.    
  14.     }  
  15.    
  16.     private void init() {  
  17.  <span style="white-space:pre">   </span>....................  
  18.   
  19.         findView(R.id.btn_go).setOnClickListener(this);  
  20.    
  21.         weatherPresenter = new WeatherPresenterImpl(this); //传入WeatherView  
  22.         loadingDialog = new ProgressDialog(this);  
  23.         loadingDialog.setTitle("加载天气中...");  
  24.     }  
  25.    
  26.     @Override  
  27.     public void onClick(View v) {  
  28.         switch (v.getId()) {  
  29.             case R.id.btn_go:  
  30.                 weatherPresenter.getWeather(cityNOInput.getText().toString().trim());  
  31.                 break;  
  32.         }  
  33.     }  
  34.    
  35.    
  36.     @Override  
  37.     public void showLoading() {  
  38.         loadingDialog.show();  
  39.     }  
  40.    
  41.     @Override  
  42.     public void hideLoading() {  
  43.         loadingDialog.dismiss();  
  44.     }  
  45.    
  46.     @Override  
  47.     public void showError() {  
  48.         //Do something  
  49.         Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();  
  50.     }  
  51.    
  52.     @Override  
  53.     public void setWeatherInfo(Weather weather) {  
  54.         WeatherInfo info = weather.getWeatherinfo();  
  55.         //更新界面  
  56.         .....................  
  57.     }  
  58.    
  59. }  
总结:

      MVP框架模式完全将Model模型和View视图分离,从而使得代码的耦合低,利用MVP框架写项目达到解耦作用。 MVP和MVC最大的区别是:MVC中的V和C关系比较紧密,耦合度太高,从C中访问M获取数据一定程度上也可以看成从V中访问M。而MVP中M和V完全分离,互相不知道对方的存在,Presenter通过接口通信方式将V和M通信。 在Android中MVP框架 Activity担当View视图层,MVC框架模式Activity担当控制器。从MVC到MVP的一个转变,就是减少了Activity的职责,减轻了它的负担,简化了Activity中的代码和一些操作,将逻辑代码提取到了Presenter中进行处理,降低了其耦合度。

      虽然MVP可以达到很好的解耦效果,可是在开发的过程中需要多写一层(Presenter)的代码,代码量会扩大,而且业务逻辑对不太熟悉的开发者来说还是略显复杂,因此建议如果开发相对较小的项目,而且项目不需要频繁的修改可以选用MVC,如果开发比较大的项目,而且需要后期不断地维护修改的话建议使用MVP框架模式开发。

mvp优点:

1、模型与视图完全分离,我们可以修改视图而不影响模型;
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部;
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁;
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值