Android MVP框架模式

结合前一篇MVC框架模式

为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生。

在MVP模式里通常包含4个要素:

(1)View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);

(2)View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;

(3)Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);

(4)Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

MVP模式步骤:1、创建一个IView让Presenter去依赖接口,不管数据时从哪里来,只要提供接口。2、让Activity或者Fragment去实现接口,实现所有View的操作。3、创建主持人,注入IView的接口,数据都从接口中获取。4、创建Model,实现数据加载(网络、数据路、假数据)5、使用主持人访问Model,获取数据后,调用IView去刷新布局。

还是使用藏头诗接口的例子

布局文件

  1     xmlns:tools="http://schemas.android.com/tools"
  2     android:id="@+id/activity_main"
  3     android:layout_width="match_parent"
  4     android:layout_height="match_parent"
  5     android:orientation="vertical"
  6     tools:context="com.example.lesson_mvc_cangtoushi.ui.MainActivity">
  7
  8     <RadioGroup
  9         android:id="@+id/rg_57"
 10         android:layout_width="match_parent"
 11         android:layout_height="wrap_content"
 12         android:orientation="horizontal">
 13
 14         <RadioButton
 15             android:id="@+id/rb_5"
 16             android:layout_width="0dp"
 17             android:layout_height="wrap_content"
 18             android:layout_weight="1"
 19             android:gravity="center"
 20             android:text="五言诗" />
 21
 22         <RadioButton
 23             android:id="@+id/rb_7"
 24             android:layout_width="0dp"
 25             android:layout_height="wrap_content"
 26             android:layout_weight="1"
 27             android:gravity="center"
 28             android:text="七言诗" />
 29     </RadioGroup>
 30
 31     <RadioGroup
 32         android:id="@+id/rg_ct"
 33         android:layout_width="match_parent"
 34         android:layout_height="wrap_content"
 35         android:orientation="horizontal">
 36
 37         <RadioButton
 38             android:id="@+id/rb_ct"
 39             android:layout_width="0dp"
 40             android:layout_height="wrap_content"
 41             android:layout_weight="1"
 42             android:gravity="center"
 43             android:text="藏头" />
 44
 45         <RadioButton
 46             android:id="@+id/rb_cw"
 47             android:layout_width="0dp"
 48             android:layout_height="wrap_content"
 49             android:layout_weight="1"
 50             android:gravity="center"
 51             android:text="藏尾" />
 52
 53         <RadioButton
 54             android:id="@+id/rb_cz"
 55             android:layout_width="0dp"
 56             android:layout_height="wrap_content"
 57             android:layout_weight="1"
 58             android:gravity="center"
 59             android:text="藏中" />
 60
 61         <RadioButton
 62             android:id="@+id/rb_dz"
 63             android:layout_width="0dp"
 64             android:layout_height="wrap_content"
 65             android:layout_weight="1"
 66             android:gravity="center"
 67             android:text="递增" />
 68
 69         <RadioButton
 70             android:id="@+id/rb_dj"
 71             android:layout_width="0dp"
 72             android:layout_height="wrap_content"
 73             android:layout_weight="1"
 74             android:gravity="center"
 75             android:text="递减"/>
 76
 77     </RadioGroup>
 78
 79     <RadioGroup
 80         android:id="@+id/rg_yy"
 81         android:layout_width="match_parent"
 82         android:layout_height="wrap_content"
 83         android:orientation="horizontal">
 84
 85         <RadioButton
 86             android:id="@+id/rb_1y"
 87             android:layout_width="0dp"
 88             android:layout_height="wrap_content"
 89             android:layout_weight="1"
 90             android:gravity="center"
 91             android:text="双句一押" />
 92
 93         <RadioButton
 94             android:id="@+id/rb_2y"
 95             android:layout_width="0dp"
 96             android:layout_height="wrap_content"
 97             android:layout_weight="1"
 98             android:gravity="center"
 99             android:text="双句押韵" />
100
101         <RadioButton
102             android:id="@+id/rb_3y"
103             android:layout_width="0dp"
104             android:layout_height="wrap_content"
105             android:layout_weight="1"
106             android:gravity="center"
107             android:text="一三四押" />
108     </RadioGroup>
109     <EditText
110         android:id="@+id/et_key"
111         android:layout_width="match_parent"
112         android:layout_height="wrap_content"
113         android:hint="请输入藏头诗"/>
114     <Button
115         android:id="@+id/btn_submit"
116         android:layout_width="match_parent"
117         android:layout_height="wrap_content"
118         android:text="提交"/>
119
120     <ScrollView
121         android:layout_width="match_parent"
122         android:layout_height="match_parent">
123         <TextView
124             android:id="@+id/tv_show"
125             android:layout_width="match_parent"
126             android:layout_height="match_parent" />
127     </ScrollView>
128
129
130
131 </LinearLayout>

activity_main.xml

java代码目录结构。可以看出MVP多了一个Presenter,主持人,还有一个View接口,极大的实现了解耦

藏头诗对象原型bean

 1 public class CangTouShiBean {
 2
 3
 4     /**
 5      * showapi_res_code : 0
 6      * showapi_res_error :
 7      * showapi_res_body : {"ret_code":0,"list":["北风勇士马,晚水独芙蓉。吾将宝非宝,英雄徒自强。","朝骑五花马,太华三芙蓉。吾将宝非宝,天子贵文强。","请歌牵白马,菡萏金芙蓉。大位天下宝,自从冒顿强。","青丝系五马,秀出九芙蓉。迈德惟家宝,日来知自强。","北买党项马,美女夸芙蓉。河宗来献宝,十年思自强。","青丝系五马,大嫂采芙蓉。药妙灵仙宝,不独有文强。"]}
 8      */
 9
10     private int showapi_res_code;
11     private String showapi_res_error;
12     private ShowapiResBodyBean showapi_res_body;
13
14
15     @Override
16     public String toString() {
17         return "CangTouShiBean{" +
18                 "showapi_res_code=" + showapi_res_code +
19                 ", showapi_res_error=‘" + showapi_res_error + ‘\‘‘ +
20                 ", showapi_res_body=" + showapi_res_body +
21                 ‘}‘;
22     }
23
24     public int getShowapi_res_code() {
25         return showapi_res_code;
26     }
27
28     public void setShowapi_res_code(int showapi_res_code) {
29         this.showapi_res_code = showapi_res_code;
30     }
31
32     public String getShowapi_res_error() {
33         return showapi_res_error;
34     }
35
36     public void setShowapi_res_error(String showapi_res_error) {
37         this.showapi_res_error = showapi_res_error;
38     }
39
40     public ShowapiResBodyBean getShowapi_res_body() {
41         return showapi_res_body;
42     }
43
44     public void setShowapi_res_body(ShowapiResBodyBean showapi_res_body) {
45         this.showapi_res_body = showapi_res_body;
46     }
47
48     public static class ShowapiResBodyBean {
49         /**
50          * ret_code : 0
51          * list : ["北风勇士马,晚水独芙蓉。吾将宝非宝,英雄徒自强。","朝骑五花马,太华三芙蓉。吾将宝非宝,天子贵文强。","请歌牵白马,菡萏金芙蓉。大位天下宝,自从冒顿强。","青丝系五马,秀出九芙蓉。迈德惟家宝,日来知自强。","北买党项马,美女夸芙蓉。河宗来献宝,十年思自强。","青丝系五马,大嫂采芙蓉。药妙灵仙宝,不独有文强。"]
52          */
53
54         private int ret_code;
55         private List<String> list;
56
57
58         @Override
59         public String toString() {
60             return "ShowapiResBodyBean{" +
61                     "ret_code=" + ret_code +
62                     ", list=" + list +
63                     ‘}‘;
64         }
65
66         public int getRet_code() {
67             return ret_code;
68         }
69
70         public void setRet_code(int ret_code) {
71             this.ret_code = ret_code;
72         }
73
74         public List<String> getList() {
75             return list;
76         }
77
78         public void setList(List<String> list) {
79             this.list = list;
80         }
81     }
82 }

CangTouShiBean.java

藏头诗Model实现藏头诗接口,请求数据,将结果回调出去

1 public interface BeanCallback<T> {
2
3     void onError(String msg);
4     void onSuccess(T t);
5 }

BeanCallback.java

1 public interface ICangTouShi {
2     //请求数据,需要有变化的参数
3     void doRequest(String num, String type, String yayuntype, String key, BeanCallback<CangTouShiBean> callback);
4
5 }

ICangTouShi.java

 1 public class CangTouShiModel implements ICangTouShi {
 2     @Override
 3     public void doRequest(String num, String type, String yayuntype, String key, final BeanCallback<CangTouShiBean> callback) {
 4
 5         //请求数据
 6         //使用OkHttp
 7
 8         OkHttpClient client = new OkHttpClient();
 9
10         RequestBody body = new FormBody.Builder()
11                 .add("showapi_appid","27306")
12                 .add("showapi_sign","150e9206e7f542bab4affe49d73cb920")
13                 .add("num",num)
14                 .add("type",type)
15                 .add("yayuntype",yayuntype)
16                 .add("key",key).build();
17
18         Request request = new Request.Builder()
19                 .post(body)
20                 .url("http://route.showapi.com/950-1").build();
21         okhttp3.Call call = client.newCall(request);
22         //异步请求,子线程
23         call.enqueue(new Callback() {
24             @Override
25             public void onFailure(okhttp3.Call call, IOException e) {
26                 Log.e("TAG","-----------"+e.getMessage());
27                 callback.onError(e.getMessage());
28             }
29
30             @Override
31             public void onResponse(okhttp3.Call call, Response response) throws IOException {
32                 String json = response.body().string();
33                 Gson gson = new Gson();
34                 CangTouShiBean bean = gson.fromJson(json, CangTouShiBean.class);
35                 callback.onSuccess(bean);
36             }
37
38         });
39
40     }
41
42 }

CangTouShiModel.java

定义一个View的接口,声明一个些方法

 1 public interface IMvpView {
 2
 3     String getNum();
 4
 5     String getType();
 6
 7     String getYY();
 8
 9     String getKey();
10
11     void showDialog();
12
13     void dismissDialog();
14
15     void setText(String text);
16
17     void showToast(String msg);
18
19 }

IMvpView.java

定义了主持人Presenter,构造方法传入以个IMvpView的对象,声明了一个CangTouModel的对象,并在构造的时候创建。然后就可以用着两个引用的方法,请求数据

 1 public class MvpPresenter {
 2     IMvpView iMvpView;
 3     ICangTouShi cangTouShi;
 4
 5     public MvpPresenter(IMvpView iMvpView){
 6         this.iMvpView = iMvpView;
 7         cangTouShi = new CangTouShiModel();
 8     }
 9
10     public void getData(){
11         //判断key不能为null
12         if(iMvpView.getKey().equals("")){
13             iMvpView.showToast("Key不能为空");
14             return;
15         }
16         iMvpView.showDialog();
17
18         cangTouShi.doRequest(iMvpView.getNum(), iMvpView.getType(), iMvpView.getYY(), iMvpView.getKey(), new BeanCallback<CangTouShiBean>() {
19             @Override
20             public void onError(String msg) {
21                 iMvpView.showToast(msg);
22                 iMvpView.dismissDialog();
23             }
24
25             @Override
26             public void onSuccess(CangTouShiBean cangTouShiBean) {
27                 String msg = "";
28                 for (String s : cangTouShiBean.getShowapi_res_body().getList()) {
29                     msg += s+"\n";
30                 }
31                 iMvpView.setText(msg);
32                 iMvpView.dismissDialog();
33             }
34         });
35
36     }
37 }

MvpPresenter.java

MainActivity加载视图,实现IMvpView的接口,实现里面的方法,拿到Presenter的对象,调用getData获取到数据。

  1 public class MainActivity extends AppCompatActivity implements IMvpView, View.OnClickListener {
  2
  3     RadioGroup rg_57, rg_ct, rg_yy;
  4     EditText et_key;
  5     Button btn_submit;
  6     TextView tv_show;
  7
  8     MvpPresenter presenter;
  9
 10     @Override
 11     protected void onCreate(Bundle savedInstanceState) {
 12         super.onCreate(savedInstanceState);
 13         setContentView(R.layout.activity_main);
 14
 15         initView();
 16         presenter = new MvpPresenter(this);
 17     }
 18
 19
 20     private void initView() {
 21         rg_57 = (RadioGroup) findViewById(R.id.rg_57);
 22         rg_57.check(R.id.rb_5);
 23         rg_ct = (RadioGroup) findViewById(R.id.rg_ct);
 24         rg_ct.check(R.id.rb_ct);
 25         rg_yy = (RadioGroup) findViewById(R.id.rg_yy);
 26         rg_yy.check(R.id.rb_1y);
 27         et_key = (EditText) findViewById(R.id.et_key);
 28         btn_submit = (Button) findViewById(R.id.btn_submit);
 29         tv_show = (TextView) findViewById(R.id.tv_show);
 30         btn_submit.setOnClickListener(this);
 31
 32
 33     }
 34
 35     @Override
 36     public String getNum() {
 37         return rg_57.getCheckedRadioButtonId() == R.id.rb_5 ? "5" : "7";
 38     }
 39
 40     @Override
 41     public String getType() {
 42         String type = null;
 43         switch (rg_ct.getCheckedRadioButtonId()){
 44             case R.id.rb_ct:
 45                 type = "1";
 46                 break;
 47             case R.id.rb_cw:
 48                 type = "2";
 49                 break;
 50             case R.id.rb_cz:
 51                 type = "3";
 52                 break;
 53             case R.id.rb_dz:
 54                 type = "4";
 55                 break;
 56             case R.id.rb_dj:
 57                 type = "5";
 58                 break;
 59         }
 60         return type;
 61     }
 62
 63     @Override
 64     public String getYY() {
 65         String yy= null;
 66         switch (rg_yy.getCheckedRadioButtonId()){
 67             case R.id.rb_1y:
 68                 yy="1";
 69                 break;
 70             case R.id.rb_2y:
 71                 yy="2";
 72                 break;
 73             case R.id.rb_3y:
 74                 yy="3";
 75                 break;
 76         }
 77         return yy;
 78     }
 79
 80     @Override
 81     public String getKey() {
 82         return et_key.getText().toString();
 83     }
 84
 85     ProgressDialog dialog;
 86     @Override
 87     public void showDialog() {
 88         dialog = new ProgressDialog(this);
 89         dialog.setTitle("提示");
 90         dialog.setMessage("开始请求");
 91         dialog.show();
 92     }
 93
 94     @Override
 95     public void dismissDialog() {
 96         dialog.dismiss();
 97     }
 98
 99     @Override
100     public void setText(final String text) {
101         runOnUiThread(new Runnable() {
102             @Override
103             public void run() {
104                 tv_show.setText(text);
105             }
106         });
107     }
108
109     @Override
110     public void showToast(final String msg) {
111         runOnUiThread(new Runnable() {
112             @Override
113             public void run() {
114                 showToast(msg);
115             }
116         });
117     }
118
119     @Override
120     public void onClick(View v) {
121         //通过主持人请求
122         presenter.getData();
123     }
124 }

MainActivity.java

对于MVP与MVC这两种模式,它们之间也有很大的差异。有一些程序员选择不使用任何一种模式,有一部分原因也许就是不能区分这两种模式差异。以下是这两种模式之间最关键的差异:

(参考文章:http://www.infragistics.com/community/blogs/todd_snyder/archive/2007/10/17/mvc-or-mvp-pattern-whats-the-difference.aspx)

MVP模式:

  • View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
  • Presenter与View的交互是通过接口来进行的,更有利于添加单元测试
  • 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑

MVC模式:

  • View可以与Model直接交互
  • Controller是基于行为的,并且可以被多个View共享
  • 可以负责决定显示哪个View
时间: 2024-10-31 00:50:12

Android MVP框架模式的相关文章

理解 Android MVP 开发模式

/***************************************************************************************** * 理解 Android MVP 开发模式 * 说明: * 最近梦真经常在提到MVP开发模式,因为我自己写APP的经验比较少,主要是需求很少,一些很 * 简单的APP也用不上,逻辑很简单,不过还是花点时间学习一下. * * 2016-9-11 深圳 南山平山村 曾剑锋 ************************

【FastDev4Android框架开发】Android MVP开发模式详解(十九)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49613861 本文出自:[江清清的博客] (一).前言: 今天我们的项目继续更新,今天我们主要讲解MVP开发模式以及具体实例. FastDev4Android框架项目地址:https://github.com/jiangqqlmj/FastDev4Android (二).简介: MVP(Model ViewPresenter)模式是著名的MVC(Model View

Android MVP框架MVPro的使用和源码分析

最近看了两篇关于Android实现MVP的文章一种在android中实现MVP模式的新思路和用MVP架构开发Android应用. 两篇文章的思路都是一样的,即把Activity.Fragment作为Presenter,这种方式不同于现在主流的MVP方式,不过它很好的解决了Activity生命周期带来的问题,而且我认为它让MVP的实现更加轻松了. 那么问题来了,这么好的思路,我们怎么可以不去实现一下自己的MVP呢? 于是我花了一晚上的时候整出了一个小小的MVP框架--MVPro MVPro介绍 M

Android MVC框架模式

MCV  model view controller  模型-视图-控制写 M层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理. V层:应用层中处理数据显示的部分,XML布局可以视为V层,显示Model层的数据结果. C层:在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据(eg.读取当前EditText控件的数据),控制用户输入(eg.EditText控件数据的输入

android MVP框架

尝试使用MVVM开发模式,让程序解耦. MVVM开发模式图: MVVM包含三个部分 Model--表示你的业务逻辑 View--显示的内容 ViewModel--把View和Model联系起来 MVVM和MVC比较: (http://blog.csdn.net/lmj623565791/article/details/46596109)

框架模式MVC与MVP在Android中的应用

很多人在开发Android项目时没有考虑过架构模式的问题,以至于随着项目的增大,Activty或者Fragment中代码也会越来越多,导致项目的维护变的越来越复杂.然而在Android中使用比较多的两种框架模式就是MVC和MVP,下面我将分别介绍一下这两种框架模式. 一.MVC框架模式 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑

框架模式MVP在Android中的使用

前一篇文章中学习了MVC框架模式在Android中的使用,不了解什么是MVC框架模式的亲戳这里 框架模式 MVC 在Android中的使用.其实谷歌Android开发团队是鼓励开发者利用MVC框架模式开发项目的,我们平时写代码也或多或少的在使用MVC框架模式开发项目,比如说谷歌自己退出来的Volley网络请求框架就是遵循MVC框架的.我们可以理解为Volley框架是MVC当中的模型,也就是网络数据处理这一块,无需跟View视图有任何关联.也符合视图和模型分离.可能你会觉得MVC框架已经很好用了,

android mvp高速开发框架介绍(dileber的简单介绍)

今天我为大家介绍一款android mvp框架:dileber(https://github.com/dileber/dileber.git) 官方交流qq群:171443726 我个人qq:297165331--有什么问题也能够咨询-- ss 随着对安卓开发的深入.越来越发现activity类简直无所不能,于是就导致activity里的代码太多,让人感觉很不爽. 近年来開始流行mvp.于是我对其进行了解,学习,參照了一些资料.自己整合了一套高速开发框架. 我将google 开发的volley,

android mvp高速开发框架介绍(dileber使用之图片下载工具)

这几天忙着工作- 今天抽时间又把框架的bug处理了一下--并且把volley的源代码改动了一下 android mvp框架:dileber(https://github.com/dileber/dileber.git) 官方交流qq群:171443726 我个人qq:297165331--有什么问题也能够咨询-- 继续解说dileber的图片下在工具 我改动了volley的NetworkImageView 的源代码--使得框架中的网络请求和图片请求都走一个接口 dileber中怎样使用下载图片的