框架模式MVP在Android中的使用

前一篇文章中学习了MVC框架模式在Android中的使用,不了解什么是MVC框架模式的亲戳这里 框架模式 MVC 在Android中的使用。其实谷歌Android开发团队是鼓励开发者利用MVC框架模式开发项目的,我们平时写代码也或多或少的在使用MVC框架模式开发项目,比如说谷歌自己退出来的Volley网络请求框架就是遵循MVC框架的。我们可以理解为Volley框架是MVC当中的模型,也就是网络数据处理这一块,无需跟View视图有任何关联。也符合视图和模型分离。可能你会觉得MVC框架已经很好用了,也能满足任何项目开发,不错,可是从上一篇博客你会发现,Controller控制器和View视图显示是在一个类Activity中体现出来的,而Android中Activity是担当Controller控制器的角色的,如果界面操作方式繁琐,视图显示复杂,那么我们不得不在Activity中添加更多的View视图显示操作,这样自然增加了Activity的代码量,也导致了Activity承担的任务和逻辑处理太多,职责不清晰。这一篇我们来介绍另外一种框架模式MVP。

MVP

MPV 是从经典的MVC模式演变过来的,其基本思路都是相通的。其中M是model模型,提供业务数据;P和MVC中的C担当的角色相似,是Presenter控制者,进行逻辑处理。V是View视图,显示数据。MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

MVC框架图MVC框架图
这里写图片描述MVP框架图

从上面的框架图可以看出MVC和MVP最大的区别就是 Model和View之间的关系。在MVC框架中,View是可以直接读取Model模型中的数据的,Model模型数据发生改变是会通知View数据显示发生相应的改变。而在MVP中Model和View之间的没有任何联系,是两个完全独立的模块,当Model模型发生数据改变时,通过Presenter通知View视图发生相应的UI改变。因此,个人觉得:MVP才是正真的视图和模型完全分离,也就是Model模型进行业务数据处理和View视图显示没有任何关联。

MVP for Android

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

同样拿上一篇的天气预报小项目来举例子:

Model模型

和MVC框架模式一样,Model模型处理数据代码不变

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

通过OnWeatherListener接口回调将Model模型处理的数据返回给Presenter控制者。

Presenter控制器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<code class = "hljs java" > /**
  * Created by xjp on 2015/6/7.
  * 天气 Presenter接口
  */
public interface WeatherPresenter {
     /**
      * 获取天气的逻辑
      */
     void getWeather(String cityNO);
 
}
..........
 
 
/**
  * Created by xjp on 2015/6/7.
  * 在Presenter层实现,给Model层回调,更改View层的状态,确保Model层不直接操作View层
  */
public interface OnWeatherListener {
     /**
      * 成功时回调
      *
      * @param weather
      */
     void onSuccess(Weather weather);
     /**
      * 失败时回调,简单处理,没做什么
      */
     void onError();
 
}
 
.........
 
package org.rocko.demos.mvp.presenter.impl;
 
import org.rocko.demos.mvp.model.WeatherModel;
import org.rocko.demos.mvp.model.entity.Weather;
import org.rocko.demos.mvp.model.impl.WeatherModelImpl;
import org.rocko.demos.mvp.presenter.OnWeatherListener;
import org.rocko.demos.mvp.presenter.WeatherPresenter;
import org.rocko.demos.mvp.ui.view.WeatherView;
 
/**
  * Created by xjp on 2015/6/7.
  * 天气 Presenter实现
  */
public class WeatherPresenterImpl implements WeatherPresenter, OnWeatherListener {
     /*Presenter作为中间层,持有View和Model的引用*/
     private WeatherView weatherView;
     private WeatherModel weatherModel;
 
     public WeatherPresenterImpl(WeatherView weatherView) {
         this .weatherView = weatherView;
         weatherModel = new WeatherModelImpl();
     }
 
     @Override
     public void getWeather(String cityNO) {
         weatherView.showLoading();
         weatherModel.loadWeather(cityNO, this );
     }
 
     @Override
     public void onSuccess(Weather weather) {
         weatherView.hideLoading();
         weatherView.setWeatherInfo(weather);
     }
 
     @Override
     public void onError() {
         weatherView.hideLoading();
         weatherView.showError();
     }
}
</code>

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

View视图

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<code class = "hljs java" > /**
  * Created by xjp on 2015/6/7.
  */
public interface WeatherView {
     void showLoading();
 
     void hideLoading();
 
     void showError();
 
     void setWeatherInfo(Weather weather);
}
</code>

然后实现Activity实现WeatherView接口

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<code class = "hljs java" > /**
  * 天气界面
  */
public class WeatherActivity extends BaseActivity implements WeatherView, View.OnClickListener {
     private Dialog loadingDialog;
     private EditText cityNOInput;
     private TextView city;
     private TextView cityNO;
     private TextView temp;
     private TextView wd;
     private TextView ws;
     private TextView sd;
     private TextView wse;
     private TextView time;
     private TextView njd;
 
     private WeatherPresenter weatherPresenter;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         init();
 
     }
 
     private void init() {
         cityNOInput = findView(R.id.et_city_no);
         city = findView(R.id.tv_city);
         cityNO = findView(R.id.tv_city_no);
         temp = findView(R.id.tv_temp);
         wd = findView(R.id.tv_WD);
         ws = findView(R.id.tv_WS);
         sd = findView(R.id.tv_SD);
         wse = findView(R.id.tv_WSE);
         time = findView(R.id.tv_time);
         njd = findView(R.id.tv_njd);
 
         findView(R.id.btn_go).setOnClickListener( this );
 
         weatherPresenter = new WeatherPresenterImpl( this ); //传入WeatherView
         loadingDialog = new ProgressDialog( this );
         loadingDialog.setTitle( "加载天气中..." );
     }
 
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
             case R.id.btn_go:
                 weatherPresenter.getWeather(cityNOInput.getText().toString().trim());
                 break ;
         }
     }
 
 
     @Override
     public void showLoading() {
         loadingDialog.show();
     }
 
     @Override
     public void hideLoading() {
         loadingDialog.dismiss();
     }
 
     @Override
     public void showError() {
         //Do something
         Toast.makeText(getApplicationContext(), "error" , Toast.LENGTH_SHORT).show();
     }
 
     @Override
     public void setWeatherInfo(Weather weather) {
         WeatherInfo info = weather.getWeatherinfo();
         city.setText(info.getCity());
         cityNO.setText(info.getCityid());
         temp.setText(info.getTemp());
         wd.setText(info.getWD());
         ws.setText(info.getWS());
         sd.setText(info.getSD());
         wse.setText(info.getWS());
         time.setText(info.getTemp());
         njd.setText(info.getNjd());
     }
 
}
</code>

因此,Activity及从MVC中的Controller中解放出来了,这会Activity主要做显示View的作用和用户交互。每个Activity可以根据自己显示View的不同实现View视图接口WeatherView。

总结

MVP框架模式完全将Model模型和View视图分离,从而使得代码的耦合性第,利用MVP框架写项目达到解耦作用。 MVP和MVC最大的区别是:MVC中的V可以从M中获取数据,而MVP中M和V完全分离,互相不知道对方的存在,Presenter通过接口通信方式将V和M通信。 在Android中MVP框架 Activity担当View视图层和MVC框架模式不一样Activity担当控制器。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值